上一篇介绍了FutureTask及简单使用,:传送门
这一篇对Future的优缺点进行分析.
一.Future的优点.
其实就很明显,能够减少程序的运行时间,因为能够同时跑很多个线程并接收返回值.
举个小例子:
public class DemoApplicationTests {
public static void main(String[] args) throws ExecutionException, InterruptedException {
ExecutorService executorService = Executors.newFixedThreadPool(3);
ArrayList<Future<String>> futureArrayList = new ArrayList<>();
//开始计时
long startTime = System.currentTimeMillis();
//执行三个耗时任务,这里每个任务耗时都为三秒
futureArrayList.add(executorService.submit(new MyThread()));
futureArrayList.add(executorService.submit(new MyThread()));
futureArrayList.add(executorService.submit(new MyThread()));
for (Future<String> future : futureArrayList) {
future.get();
}
System.out.println("最终耗时:"+(System.currentTimeMillis()-startTime)/1000);
executorService.shutdown();
}
}
class MyThread implements Callable<String>{
@Override
public String call() throws Exception {
//进行耗时操作
Thread.currentThread().sleep(3000);
return "hello";
}
}
输出结果:
可以看到在此条件下减少了60%的运行时间.
二.Future的缺点.
它的缺点其实也比较明显:
1.对于返回值的获取不太友好
当执行get()方法的时候,它会进行阻塞,一直等到有结果返回,当然还可以传入一个超时时间,如果超过时间,会抛出异常.
在我们进行使用的时候,一般会有两种写法:
第一种:指定超时时间并捕获异常处理
第二种:轮询获取
这两种需要根据不同的业务场景进行选择.
2.不能对任务进行优先返回
假如现在有三个任务,第一个任务耗时10s,第二个任务耗时3s,第三个任务耗时5s,我们将其提交给线程池,并将返回结果放到一个list中去依次获取
其实我们已经知道第二、三个任务会优先执行完毕,但是却必须等第一个任务get()出结果后才能继续处理,这种在一些场景下就会浪费时间了.
三.总结
正是因为Futrue有自身的一些缺点,这才引出了CompletableFuture,下一篇将着重讲解CompletableFuture的特点和使用.