Java并发35:Callable+Future系列--Future接口学习笔记
1.Future接口概述
Future接口代表着异步计算的结果。
Future接口提供了一些方法:查看计算是否完成、等待计算完成和获取计算结果。
只有在计算完成时,才能通过get()方法获取计算结果,必要时程序会阻塞直到计算完成。
取消计算是通过方法cancel()执行的。
此外,还提供了一些其他的方法用于确认任务是否正常(isDone())或者是否取消(isCancelled())。
一旦一个计算已经完成,则这个计算不能再被取消。
如果你因为可取消性而想使用Future接口,但是又不能提供一个可用的计算结果,那么你可以将其声明为Future<?>类型,并且以null值作为返回值。
示例用法
interface ArchiveSearcher { String search(String target); } class App { ExecutorService executor = ... ArchiveSearcher searcher = ... void showSearch(final String target) throws InterruptedException { Future<String> future = executor.submit(new Callable<String>() { public String call() { return searcher.search(target); } }); displayOtherThings(); // do other things while searching try { displayText(future.get()); // use future } catch (ExecutionException ex) { cleanup(); return; } } }
谨记一致性影响:
一个线程池中异步计算的结果 happens-before 另一个线程中Future.get()方法之后的操作。
也就是说: 一个线程池中异步计算的结果 对 另一个线程中 Future.get()方法 之后的操作 可见。
2.Future的方法说明
Future的方法如下:
1.isDone():任务是否完成
2.isCancelled():任务是否取消了
3.cancel(mayInterruptIfRunning):
取消任务:
- mayInterruptIfRunning = true:如果任务在运行,则即使中断任务,也要取消任务。
- mayInterruptIfRunning = false:如果任务在运行,则等待任务运行完毕,再取消任务。
4.get():
阻塞的的获取计算结果,直到发生以下三种情况之一:
- 获取了计算结果,返回结果。
- 当前线程被中断被中断,抛出InterruptedException异常。
- 计算出错,则抛出ExecutionException异常。
5.get(timeout,TimeUnit):
在限定时间内,阻塞的的获取计算结果,直到发生以下四种情况之一:
- 获取了计算结果,则返回结果。
- 当前线程被中断被中断,则抛出InterruptedException异常
- 计算出错,则抛出ExecutionException异常。
- 等待时间超时,则抛出TimeoutException异常。
3.实例练习
练习目的:熟悉Future各方法的使用。
练习描述:
isDone()和isCancelled()的使用
cancel(true)的使用
get(timeout,TimeUnit)的使用
get()的使用
实例代码:
//定义一个线程池 ExecutorService executorService = Executors.newCachedThreadPool(); //定义一个Callable对象 Callable callable = new Callable() { @Override public Object call() throws Exception { //模拟开始计算 try { Thread.sleep(5000); } catch (InterruptedException e) { //e.printStackTrace(); System.out.println("正在计算,被取消了"); } //计算结束,返回结果 return 100; } }; //提交一个Callable任务,返回一个Future对象 Future<Integer> future = executorService.submit(callable); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } //isDone():任务是否完成 System.out.println("1000ms的时候计算是否完成:" + future.isDone()); //isCancelled():任务是否取消了 System.out.println("1000ms的时候计算是否取消:" + future.isCancelled()); System.out.println(); //cancel取消-true表示即使在运行也取消,false表示如果没运行可以取消 future.cancel(true); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } //isDone():任务是否完成 System.out.println("cancel之后计算是否完成:" + future.isDone()); //isCancelled():任务是否取消了 System.out.println("cancel之后计算是否取消:" + future.isCancelled()); System.out.println(); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } //再次提交一个Callable任务,返回一个Future对象 future = executorService.submit(callable); //在2秒时限内尝试去获取 //获取到则返回结果 //获取不到则返回 try { System.out.println("在2秒时限内尝试去获取:" + future.get(2, TimeUnit.SECONDS)); } catch (TimeoutException e) { //e.printStackTrace(); System.out.println("timeout超时,抛出TimeoutException异常"); } catch (InterruptedException e) { //e.printStackTrace(); System.out.println("线程interrupt,抛出InterruptedException异常"); } catch (ExecutionException e) { //e.printStackTrace(); System.out.println("执行出错,抛出ExecutionException异常"); } //isDone():任务是否完成 System.out.println("get(timeout,TimeUnit)超时之后,计算是否完成:" + future.isDone()); //isCancelled():任务是否取消了 System.out.println("get(timeout,TimeUnit)超时之后,cancel之后计算是否取消:" + future.isCancelled()); System.out.println(); //阻塞的等待计算结果,直到获取计算结果 try { System.out.println("阻塞的等待计算结果,直到获取计算结果:" + future.get()); } catch (InterruptedException e) { //e.printStackTrace(); System.out.println("线程interrupt,抛出InterruptedException异常"); } catch (ExecutionException e) { //e.printStackTrace(); System.out.println("执行出错,抛出ExecutionException异常"); } //isDone():任务是否完成 System.out.println("get()之后,计算是否完成:" + future.isDone()); //isCancelled():任务是否取消了 System.out.println("get()之后,cancel之后计算是否取消:" + future.isCancelled()); //取消线程池 executorService.shutdown();
运行结果:
1000ms的时候计算是否完成:false 1000ms的时候计算是否取消:false 正在计算,被取消了 cancel之后计算是否完成:true cancel之后计算是否取消:true timeout超时,抛出TimeoutException异常 get(timeout,TimeUnit)超时之后,计算是否完成:false get(timeout,TimeUnit)超时之后,cancel之后计算是否取消:false 阻塞的等待计算结果,直到获取计算结果:100 get()之后,计算是否完成:true get()之后,cancel之后计算是否取消:false