没太看明白FutureTask的方便和线程数
来源:7-2 J.U.C-FutureTask-2

Echo鑫
2018-03-23
老师,可能是看久了,头有点懵
Future类中,
ExecutorService executorService = Executors.newCachedThreadPool();
Future<String> future = executorService.submit(new MyCallable());
log.info("do something in main");
Thread.sleep(1000);
String result = future.get();
log.info("result:{}", result);
实例化一个线程池,开启一个线程,去接收MyCallable中的结果,然后future.get获得结果,
再看futureTask类
new Thread(futureTask).start();
log.info("do something in main");
Thread.sleep(1000);
String result = futureTask.get();
log.info("result:{}", result);
futureTask也是开了个线程接收返回结果,直观来看,菜鸟基本都会觉得第一种写法,少了个线程启动start,反而要方便些,作用跟第二种也差不多。
问题:
这两种方式,分别是开了几个线程,我有点不太理解,该怎么算线程。
既然Task是单独开启一个线程,来存放所监督的线程返回结果,第一个future中,直接在线程池多拿个线程出来,效果不是一样的?
(这问,也是由于没太明白这两个例子中线程数该怎么算,我觉得把线程数说出来,比如我理解的是,第一个例子,开启一个线程,做了两件事,第二个例子,开启两个线程,分别做了某一件事,理解起来更方便,当然我这理解可能是错的)
1回答
-
你好,其实关于FutureTask,你问的那两个问题不是关键,我来具体说一下。
先说Future。Executor是Runnable和Callable的调度容器,Future是对于具体的Runnable或者Callable任务的执行结果进行取消、查询是否完成、获取结果、设置结果操作。其实很好用。
而FutureTask呢,是一个RunnableFuture< V>,而RunnableFuture实现了Runnbale又实现了Futrue< V>这两个接口,他还可以包装Runnable和Callable< V>,看他的构造函数,可以知道Runnable注入会被Executors.callable()函数转换为Callable类型,即FutureTask最终都是执行Callable类型的任务,具体可以看callable()方法和 RunnableAdapter适配器。由于FutureTask实现了Runnable,因此它既可以通过Thread包装来直接执行,也可以提交给ExecuteService来执行。并且还可以直接通过get()函数获取执行结果,该函数会阻塞,直到结果返回。因此FutureTask既是Future、Runnable,又是包装了Callable(如果是Runnable最终也会被转换为Callable ), 它是这两者的合体。
课程里的例子不是为了表达相比Future的写法好在哪里,而是给出另外的用法。可以根据实际需要选择不同的写法。Future、Runnable、Callable支持的,FutureTask都能满足。
看看现在是否明白啦~
312018-03-24
相似问题