1. FutureTask 简介

在 Executors 框架体系中,FutureTask 用来表示可获取结果的异步任务。

FutureTask 提供了启动和取消异步任务,查询异步任务是否计算结束以及获取最终的异步任务的结果的一些常用的方法。通过get()方法来获取异步任务的结果,但是会阻塞当前线程直至异步任务执行结束。一旦任务执行结束,任务不能重新启动或取消,除非调用runAndReset()方法。

  • Future 接口
    • 可以监视目标线程调用 call 的情况,当你调用 future 的 get 方法的时候就可以获取结果。
  • FutureTask 类

    • 实现了 RunnableFuture 接口,而 RunnableFuture 继承了 Future 和 Runnable
    • image.png
    • 既可以作为 Runnable 执行,又可以作为 Future 得到返回值。比如一个费时操作,可以先执行其他操作,再得到线程返回值。
  • get 方法:

    • 当FutureTask 处于未启动或已启动状态时,执行FutureTask.get()方法将导致调用线程阻塞。如果FutureTask 处于已完成状态,调用FutureTask.get()方法将导致调用线程立即返回结果或者抛出异常
  • cancel 方法
    • 当 FutureTask 处于未启动状态时,执行FutureTask.cancel()方法将此任务永远不会执行
    • 当 FutureTask 处于已启动状态时,执行FutureTask.cancel(true)方法将以中断线程的方式来阻止任务继续进行,执行FutureTask.cancel(false)将不会对正在执行任务的线程有任何影响;
  • FutureTask 处于已完成状态时,执行FutureTask.cancel(...)方法将返回 false。

对 Future 的get()方法和cancel()方法用下图进行总结:
image.png

2. FutureTask 的基本使用

  1. public class FutureExample {
  2. static class MyCallable implements Callable<String> {
  3. @Override
  4. public String call() throws Exception {
  5. log.info("do something in callable");
  6. Thread.sleep(5000);
  7. return "Done";
  8. }
  9. }
  10. public static void main(String[] args) throws Exception {
  11. ExecutorService executorService = Executors.newCachedThreadPool();
  12. Future<String> future = executorService.submit(new MyCallable());
  13. log.info("do something in main");
  14. Thread.sleep(1000);
  15. String result = future.get();
  16. log.info("result:{}", result);
  17. }
  18. }

执行结果:

  1. - do something in main
  2. - do something in callable
  3. - resultDone

FutureTask 方式实现

  1. public static void main(String[] args) throws Exception {
  2. FutureTask<String> futureTask = new FutureTask<String>(new Callable<String>() {
  3. @Override
  4. public String call() throws Exception {
  5. log.info("do something in callable");
  6. Thread.sleep(5000);
  7. return "Done";
  8. }
  9. });
  10. new Thread(futureTask).start();
  11. log.info("do something in main");
  12. Thread.sleep(1000);
  13. String result = futureTask.get();
  14. log.info("result:{}", result);
  15. }

A Demo

  1. import java.util.concurrent.Callable;
  2. import java.util.concurrent.ExecutorService;
  3. import java.util.concurrent.Executors;
  4. import java.util.concurrent.Future;
  5. public class main {
  6. public static void main(String[] args) {
  7. try {
  8. Thread.sleep(5000);// 可能做一些事情
  9. } catch (InterruptedException e) {
  10. e.printStackTrace();
  11. }
  12. DoService doService = new DoService();
  13. DoService.doAsyncTask(doService.new CallThread());
  14. }
  15. }
  16. class DoService {
  17. private static ExecutorService service = Executors.newFixedThreadPool(6);
  18. public static Future<Object> doAsyncTask(Callable<Object> call) {
  19. if (call == null) {
  20. return null;
  21. }
  22. return service.submit(call);
  23. }
  24. public class CallThread implements Callable<Object> {
  25. public Object call() throws Exception {
  26. Thread.sleep(2000);
  27. System.out.println("Do something complex...");
  28. return "success";
  29. }
  30. }
  31. }