巩固 Java Future 的使用
Future 还是一 Java 1.5 带进来的产物,但过去那么多年实际代码中却很少有直接接触, 大约它多是隐匿在各种现成框架中默默的为我们服务。Future 本身不代表着多线程,而是代表着需异步计算的结果, 将来的一个期待,至于后来真正的结果不可知。在此之前想要获得一个 Runnable 在其他线程中的计算结果颇费波折,有了 Future 加之它身后的 Callable 一切就变得简单了。
对比一下 Java 1.5 前后的下面几个概念
只有 callable 被提交(到线程池) 后返回的 Future 才可能会有结果, 所以下面的代码永远等不到结果
最容易理解的 Future 基本使用代码如下:
上面代码的执行结果如下
Future 的其他几个方法如下:
boolean cancel(boolean mayInterruptIfRunning): 可以取消一个任务,调用能否成功因情况而定
boolean isCancelled()
boolean isDone()
我们也可以通过查询
Future 解决了线程返回值的问题,但到了 Java 8 还不够,我们还需要处理多个 Future 之间的依赖,竞争关系,因此又带来了更强悍的 Future 的新实现 CompletableFuture。
进一步学习当中......
补充一下,在 Java 1.5 之前想要获得线程的执行结果可以参考如下代码
因为
[版权声明]
本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。
对比一下 Java 1.5 前后的下面几个概念
- Callable 相当于之前的 Runnable, 只是 Callable 是有返回值的
- ExecuteService.submit(callable): Future 就类似于之前的 Thread(runnable)
只是前者 submit 后立即执行,通过 get() 获得结果,后者用 start() 方法启动,runnable 是没有结果的。如果你也不想关心 Future 的结果也能 ExecuteService.submit(runnable)
只有 callable 被提交(到线程池) 后返回的 Future 才可能会有结果, 所以下面的代码永远等不到结果
Futurefuture = new FutureTask<>(() -> "Never");
String result = future.get();
最容易理解的 Future 基本使用代码如下:
1 ExecutorService executor = Executors.newCachedThreadPool(); //这是众多线程池类型的一种
2 Future<String> future = executor.submit(() -> { //Lambda 是一个 callable, 提交后便立即执行,这里返回的是 FutureTask 实例
3 System.out.println("Running task...");
4 Thread.sleep(5000);
5 return "Task return";
6 });
7
8 try {
9 Thread.sleep(1000);
10 } catch (InterruptedException e) {
11 }
12
13 System.out.println("Do something else"); //前面的的 Callable 在其他线程中运行着,现在想做别的事情都不影响
14
15 try {
16 System.out.println(future.get()); //等待 future 的执行结果
17 } catch (InterruptedException | ExecutionException e) {
18 }
19
20 executor.shutdown(); //不关闭的话程序都不会退出上面代码的执行结果如下
Running task...可以看出任务 submit() 之后立即执行,相当于
Do something else
Task return
new Thread(...).start(). 注意 future.get() 需强制捕获的异常,它还有一个重载方法 future.get(long timeout, TimeUnit unit), 指定等待多长时间,超时报 TimeoutException. 无参的 get() 永远的等待。Future 的其他几个方法如下:
boolean cancel(boolean mayInterruptIfRunning): 可以取消一个任务,调用能否成功因情况而定
boolean isCancelled()
boolean isDone()
我们也可以通过查询
isDone() 看任务是否执行完成,比如1while(!future.isDone()) {
2 Thread.sleep(1000);
3 System.out.println("Waiting....")
4}
5future.get(); //到这时 future 已经执行完Future 解决了线程返回值的问题,但到了 Java 8 还不够,我们还需要处理多个 Future 之间的依赖,竞争关系,因此又带来了更强悍的 Future 的新实现 CompletableFuture。
进一步学习当中......
补充一下,在 Java 1.5 之前想要获得线程的执行结果可以参考如下代码
1// AtomicReference<String> reference = new AtomicReference<>();
2
3 StringBuffer sb = new StringBuffer();
4
5 new Thread(() -> {
6 try {
7 Thread.sleep(5000);
8 } catch (InterruptedException e) {
9 e.printStackTrace();
10 }
11 // reference.set("I'm done");
12 sb.append("I'm done");
13 }).start();
14
15// while(reference.get() == null) {
16// }
17
18// System.out.println(reference.get());
19
20 while(sb.length() == 0) {
21 }
22
23 System.out.println(sb.toString());因为
AtomicReference 也是来自于 JDK 1.5 的 concurrent 的 API,所以用了早先线程安全的 StringBuffer 类。
永久链接 https://yanbin.blog/consolidate-use-of-java-future/, 来自 隔叶黄莺 Yanbin's Blog[版权声明]
本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。