JUC学习-16-浅谈Callable和FutureTask
JUC学习-16-浅谈Callable和FutureTask
一、一般情况下,使用Runnbale接口、Thread实现的线程 我们都是无法返回结果的。但是如果对一些场合需要线程返回结果,就要使用Callable和Future这几个类。Callable只能在ExecutorService的线程池中跑,但有返回结果,也可以通过返回的Future对象查询执行状态。
二、Future本身也是一种设计模式,它是用来取得异步任务的结果
看看其源码:
Callable类中只有一个call方法,并且有一个返回V,是泛型。可以认为这里返回V就是线程返回的结果。
@FunctionalInterface // 函数式接
public interface Callable<V> {
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
V call() throws Exception;
}
三、一般通过使用FutureTask类来包装Callable对象,然后将FutureTask对象作为参数传递给Thread
public class CallableTest {
public static void main(String[] args) {
/* // 第一步 创建Callable实现类的实例,并实现call方法
class Task implements Callable<Integer> {
@Override
public Integer call() throws Exception {
return 5;
}
}
// 第二步 创建Callable实现类实例
Task task = new Task();
}*/
// 第三步 使用FutureTask类包装Callable对象,可以创建匿名对象
// 也可以直接使用lambda表达式 从而省略1 2 步骤
FutureTask<Integer> future = new FutureTask(() -> {
System.out.println("2.子线程运行中...");
return 5;
});
// 第四步 使用Future Task对象作为 Thread对象的target创建、并启动新线程
new Thread(future).start();
System.out.println("1.已启动...");
try {
// FutureTask的get()方法会自动阻塞,直到得到任务执行结果位置
Integer value = future.get();// 第五步 调用FutureTask对象的方法来回去子线程执行结束后的返回值
System.out.println("3.返回值" + value);
} catch (InterruptedException e) {
throw new RuntimeException(e);
} catch (ExecutionException e) {
throw new RuntimeException(e);
}
}
}
返回结果:
结论:当主线程执行start()方法后开启子线程,此时主线程是异步调用,会继续往下执行。当执行到future.get()后,会查看子线程是否执行完毕(返回值)。如果未执行完毕会阻塞等待,主线程获取到子线程的返回值后 才会继续向下执行。
本文来自博客园,作者:skystrivegao,转载请注明原文链接:https://www.cnblogs.com/skystrive/p/18983416
整理不易,如果对您有所帮助 请点赞收藏,谢谢~