方法三实现Callable接口
package cn.anzhongwei.lean.demo.thread;
import java.util.Random;
import java.util.concurrent.*;
/**
* 和Runnable接口不一样,Callable接口提供了一个call()方法作为线程执行体,call()方法比run()方法功能要强大。
*
* call()方法可以有返回值
*
* call()方法可以声明抛出异常
*
* Java5提供了Future接口来代表Callable接口里call()方法的返回值,并且为Future接口提供了一个实现类FutureTask,这个实现类既实现了Future接口,还实现了Runnable接口。
* 因此可以作为Thread类的target。在Future接口里定义了几个公共方法来控制它关联的Callable任务。
* public interface Future<V> {
* //视图取消该Future里面关联的Callable任务
* boolean cancel(boolean mayInterruptIfRunning);
* //如果在Callable任务正常完成前被取消,返回True
* boolean isCancelled();
* //若Callable任务完成,返回True
* boolean isDone();
* //返回Callable里call()方法的返回值,调用这个方法会导致程序阻塞,必须等到子线程结束后才会得到返回值
* V get() throws InterruptedException, ExecutionException;
* //返回Callable里call()方法的返回值,最多阻塞timeout时间,经过指定时间没有返回抛出TimeoutException
* V get(long timeout, TimeUnit unit)
* throws InterruptedException, ExecutionException, TimeoutException;
* }
*
* 介绍了相关的概念之后,创建并启动有返回值的线程的步骤如下:
*
* 1】创建Callable接口的实现类,并实现call()方法,然后创建该实现类的实例(从java8开始可以直接使用Lambda表达式创建Callable对象)。
*
* 2】使用FutureTask类来包装Callable对象,该FutureTask对象封装了Callable对象的call()方法的返回值
*
* 3】使用FutureTask对象作为Thread对象的target创建并启动线程(因为FutureTask实现了Runnable接口)
*
* 4】调用FutureTask对象的get()方法来获得子线程执行结束后的返回值
*/
public class M03ImplementCallable01 {
public static void main(String[] args) {
//1. 此处使用的是匿名类方式
// Callable<String> callable = new Callable<String>() {
// public String call() throws Exception {
// for(int i = 0; i < 3; i++) {
// System.out.println("callable线程输出"+i);
// }
// return "返回随机数"+(new Random().nextInt(100));
// }
// };
//2. 使用静态内部类
Callable<String> callable = new InnerStaticCallable();
//3. 使用外部实现类。略
FutureTask<String> future = new FutureTask<String>(callable);
Thread thread = new Thread(future);
thread.start();
try {
String resI = future.get();
System.out.println(resI);
} catch (InterruptedException ie) {
ie.printStackTrace();
} catch (ExecutionException ee) {
ee.printStackTrace();
}
//此种方法可以用, 但是不明确应用场景, 返回资源的值是在new FutureTask中传入的,
//runnable接口实现直接使用Thread的start方法运行就行,传到FutureTask中有啥用
Runnable runnable = new Runnable() {
@Override
public void run() {
for(int i = 0; i < 3; i++) {
System.out.println("Runnable线程输出"+i);
}
}
};
FutureTask<Integer> target = new FutureTask<>(runnable, 12);
Thread thread1 = new Thread(target);
thread1.start();
try {
Integer resI1 = target.get();
System.out.println(resI1);
} catch (InterruptedException ie) {
ie.printStackTrace();
} catch (ExecutionException ee) {
ee.printStackTrace();
}
System.out.println("主线程输出");
}
//也可以使用内部类方式
static class InnerStaticCallable implements Callable<String> {
@Override
public String call() {
for(int i = 0; i < 3; i++) {
System.out.println("callable线程输出"+i);
}
return "返回随机数"+(new Random().nextInt(100));
}
}
}