https://blog.csdn.net/weixin_44863537/article/details/113354411
Callable和Future的关系
-
可以用
Future.get
来获取Callable接口返回的执行结果,还可以通过Future.isDone()
来判断任务是否已经执行完了 -
在call()未执行完毕之前,调用get()的线程(假定此时是主线程)会被阻塞,直到call方法返回了结果后,此时future.get才会得到结果,然后主线程才会切换到runnable状态
-
Future是一个存储器,存储了call()这个任务的结果,而这个任务的执行时间是无法提前确定的
Future主要方法
-
get()
:获取结果。get方法的行为取决于Callable任务的状态
-
任务正常完成:get方法会立刻返回结果
-
任务尚未完成(任务还没开始或进行中):get将阻塞直到任务完成
-
任务执行过程中抛出Exception:get方法也会抛出ExecutionException,在运行到get才会抛出
-
任务被取消:get方法会抛出CancellationException
-
任务超时:get方法有个重载方法,需要传入延迟时间,过了时间还没获得结果,get方法就抛出TimeoutException
-
-
get(long timeout, TimeUnit unit)
:有超时的获取 -
cancel()
:取消任务的执行 -
isDone()
:判断线程是否执行完毕 -
isCancelled()
:判断是否被取消
Future用法一
-
线程池的submit方法返回Future对象
-
具体过程:向线程池提交任务,提交时线程池会立刻返回一个空的Future容器。当线程的任务执行完毕,可以获取结果时,线程池便将结果填入那个Future容器中
-
下面例子演示 get() 最基本的使用方法
public class OneFuture { public static void main(String[] args) { ExecutorService service = Executors.newFixedThreadPool(10); Future<Integer> future = service.submit(new CallableTask()); try { System.out.println(future.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } service.shutdown(); } static class CallableTask implements Callable<Integer> { @Override public Integer call() throws Exception { Thread.sleep(3000); return new Random().nextInt(); } } } 12345678910111213141516171819202122232425
-
批量接收结果
public class MutilFutures { public static void main(String[] args) throws InterruptedException { ExecutorService service = Executors.newFixedThreadPool(20); ArrayList<Future> futures = new ArrayList<>(); for (int i = 0; i < 20; i++) { Future<Integer> future = service.submit(new CallableTask()); futures.add(future); } Thread.sleep(5000); for (int i = 0; i < 20; i++) { try { Future future = futures.get(i); Object o = future.get(); System.out.println(o); } catch (ExecutionException e) { e.printStackTrace(); } } } static class CallableTask implements Callable<Integer> { @Override public Integer call() throws Exception { Thread.sleep(3000); return new Random().nextInt(); } } } 1234567891011121314151617181920212223242526272829
-
cancel方法:
Future.cancel(true)适用于任务能够处理interrupt
Future.cancel(false)仅仅用于避免启动尚未启动的任务,适用于:
-
未能处理interrupt的任务
-
不清楚任务是否能够取消
-
需要等待已经开始的任务执行完成
-
Future用法二
-
用FutureTask来获取Future和任务的结果
-
FutureTask是一种包装器,可以将Callable转化成Future和Runnable,同时实现了二者的接口
-
用法:把Callable实例当作参数,生成FutureTask的对象,然后把这个对象当作Runnable对象,用线程池或者另起线程去执行这个Runnable对象,最后通过FutureTask获取结果
public class FutureTaskDemo { public static void main(String[] args) { Task task = new Task(); FutureTask<Integer> integerFutureTask = new FutureTask<>(task); // new Thread(integerFutureTask).start(); ExecutorService service = Executors.newCachedThreadPool(); service.submit(integerFutureTask); try { System.out.println("task运行结果:"+integerFutureTask.get()); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } } class Task implements Callable<Integer> { @Override public Integer call() throws Exception { System.out.println("子线程正在计算"); Thread.sleep(3000); int sum = 0; for (int i = 0; i < 100; i++) { sum += i; } return sum; } } 123456789101112131415161718192021222324252627282930313233