之前在看《Java程序员修炼之道》(主要讲的是Java 7的新特性)的时候就看过并发这块儿,但是感觉看完过段儿时间印象也有点儿模糊。最近重温Java并发编程,拿起了《Java并发编程实战》,只能用四个字儿来形容:干货太多。书里讲的几乎没有废话,大部分例子也都不错,对于理解新的Java并发编程模型很有帮助。不过,也有些例子可能受篇幅所限,讲解的不够细致,所以我就需要从网上再找些相对丰富的例子补充上以加深理解。Future就是其中一例。
下面的代码段摘自java.util.concurrent.Future Basics,感觉这篇教程讲解虽然基础但是很清晰,看看代码基本上就理解Future的简单用法了。
单线程应用
1 2 3 4 5 6 7 8 9
| public String downloadContents(URL url) throws IOException { try(InputStream input = url.openStream()) { return IOUtils.toString(input, StandardCharsets.UTF_8); } } //... final String contents = downloadContents(new URL("http://www.example.com"));
|
使用Future接口,并行处理
1 2 3 4 5 6 7
| public static Future<String> startDownloading(URL url) { //... } final Future<String> contentsFuture = startDownloading(new URL("http://www.example.com")); //other computation final String contents = contentsFuture.get();
|
调用isDone方法判断是否执行完成
1 2 3 4 5 6
| final Future<String> contentsFuture = startDownloading(new URL("http://www.example.com")); while (!contentsFuture.isDone()) { askUserToWait(); doSomeComputationInTheMeantime(); } contentsFuture.get();
|
取消任务
1
| contentsFuture.cancel(true);
|
两种获得Future实例的方法
使用线程池
1 2 3 4 5 6 7 8 9 10 11 12
| private final ExecutorService pool = Executors.newFixedThreadPool(10); public Future<String> startDownloading(final URL url) throws IOException { return pool.submit(new Callable<String>() { @Override public String call() throws Exception { try (InputStream input = url.openStream()) { return IOUtils.toString(input, StandardCharsets.UTF_8); } } }); }
|
使用容器,如Spring或EJB
1 2 3 4 5 6 7 8
| @Async public Future<String> startDownloading(final URL url) throws IOException { try (InputStream input = url.openStream()) { return new AsyncResult<>( IOUtils.toString(input, StandardCharsets.UTF_8) ); } }
|
代码实例能帮助理解,同时也要通读一下原文,注意其中的一些细节,比如超时和中断的处理逻辑等等。
最后,我们摘抄《Java并发实战》第7章的例子看看相对完整的一个取消操作是怎么完成的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public static void timedRun(Runnable r, long timeout, TimeUnit unit) throws InterruptedException { Future<?> task = taskExec.submit(r); try { task.get(timeout, unit); } catch(TimeoutException e) { } catch(ExecutionException e){ throw launderThrowable(e.getCause()); } finally { task.cancel(true); } }
|
参考资源