最近发现关于ExecutorService的理解容易错误,会只是把它当成多线程的思想来理解,但这样的理解其实是不对的很片面的,所以简单讲讲我的个人理解。
private ExecutorService executorService=null;
if (executorService == null) {
executorService = Executors.newCachedThreadPool();//这里创建一个线程池
}
//提交任务
Future<String> future = executorService.submit(new Callable<String>() {
@Override
public String call() throws Exception {
// TODO: 2021/3/27
Thread.sleep(10000);
return "result";
}
});
......
//阻塞获取结果
String result=future.get();
//任务集合调用
List<Callable<String>> all = new ArrayList<>();
....添加任务
List<Future<String>> fs = executorService.invokeAll(all);//这里要稍微注意下,这个是阻塞的,看源码就知道List<Future<String>>已经是所有任务完成后的结果集了,没有单个执行灵活。
使用很简单,我们可以看到,显示创建了一个线程池,然后提交任务返回一个任务凭证Future,当你需要用到结果的时候再去阻塞get()使用,所以整个的实现关键一个是线程池,一个是Future;线程池其实你自己new一个Thread也就有了,Future反而是关键。 所以这里的中心思想是【期货】
, Future这里可以理解为未完成的货物或功能
,也就是期货中的票剧(为什么piaoju是敏感词。。。),线程池就是期货公司。整个过程是这样的:
- 你去期货公司买期货,于是期货公司派了一个对接人(也就是线程)来跟你对接。
- 你说我要买一吨苹果,那期货公司肯定没有现成的,于是给你开了个单子(也就是Future)
- 期货公司有了货之后改变订单状态(这里不是订阅通知的模型,只是改变Future的状态,因为订阅通知需要你设置回调对象的,这样就没办法做到异步执行同步调用了)
- 或者你实在急用(主线程执行要快),那你直接就睡到期货公司等着(阻塞的get),取到货后一个订单就完成了。
- 当然你还可以同时买一吨苹果一吨梨一吨桔子,这样你就有了个三个单子,三个人给你办事(当然期货公司就一个人,也就是线程池只有一个线程)。
- 整个交易的时间就是三个人中办事最慢的那个的时间。
所以不要理解错因果关系,是因为要实现期货这个模型需要多线程,并不是有了多线程它就是期货。