文章目录
如果你的意图是实现并发,而非并行,或者你的主要目标是在同一个CPU上执 行几个松耦合的任务,充分利用CPU的核,让其足够忙碌,从而大化程序的吞吐量。
那么你其实真正想做的是避免因为等待远程服务的返回,或者对数据库的查询,而阻塞线程的执行, 浪费宝贵的计算资源,因为这种等待的时间很可能相当长。
比如想查询一个商品的详情,包括价格。查询价格是另一个服务,但是又不想因为查询价格阻塞其他信息的查询(比如库存量)。那么可以了解一下CompletableFuture。
Future接口
Future接口在Java5中被引入,可以实现一种异步计算,返回一个执行运算结果的引用,当运算结束后,这个引用被返回给调用方。
在 Future中触发那些潜在耗时的操作把调用线程解放出来,让它能继续执行其他有价值的工作, 不再需要呆呆等待耗时的操作完成。打个比方,你可以把它想象成这样的场景:你拿了一袋子衣 服到你中意的干洗店去洗。干洗店的员工会给你张发票,告诉你什么时候你的衣服会洗好(这就 是一个Future事件)。衣服干洗的同时,你可以去做其他的事情。
Long start = System.nanoTime();
ExecutorService executor = Executors.newCachedThreadPool();
Future<Integer> future = executor.submit(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return doSomeLongCompution();
}
});
doSomethingElse();
System.out.println((System.nanoTime() - start)/1000000);
try {
Integer result = future.get(5, TimeUnit.SECONDS);
System.out.println((System.nanoTime() - start)/1000000);
} catch (Exception e) {
e.printStackTrace();
}
这种编程方式让你的线程可以在ExecutorService以并发方式调用另一个线程执行耗时操作的同时,去执行一些其他的任务。
接着,如果你已经运行到没有异步操作的结果就无法继续任何有意义的工作时,可以调用它的get方法去获取操作的结果。
如果操作已经完成,该方法会立刻返回操作的结果,否则它会阻塞你的线程,直到操作完成,返回相应的结果。
这个场景存在一个问题,如果该长时间运行的操作永远不返回会一直阻塞,所以推荐使用get方法的时候可以加一个超时参数。避免一直等待。