java线程之——FutureTask

一、FutureTask的实现

FutureTask实现了RunnableFuture,既即实现Runnable接口和Future接口。所以FutureTask实现run方法,以及Future接口的一系列计算结果方法

二、构造方法

FutureTask有两个构造方法,分别为一个参数和两个参数,如下图:

一个参数构造器传入一个Callable实现,需要返回参数;

第二个构造器第一个参数传入Runnable实现,不需要返回参数,但是需要再第二个参数指定返回值;

如下:

  public static void test1() throws Exception {
    // FutureTask封装一个线程
    FutureTask<String> future = new FutureTask<>(() -> {
      System.out.println("work...");
      Thread.sleep(3000);
      throw new Exception("神奇");
      // return "工作完成";
    });
    // run运行线程,不会返回结果,线程异常不会被抛出,get时才会抛出异常
    future.run();
    // get等待任务执行完成,并返回结果
    System.out.println(future.get());
  }

  public static void test2() throws Exception {
    FutureTask<String> futureTask = new FutureTask<>(() -> System.out.println("work"), "OK");
    futureTask.run();
    System.out.println(futureTask.get());
  }

 

三、方法

1、run():同线程的run方法,执行FutureTask的线程run方法,该方法不会抛出线程内部的异常。如果在之前FutureTask已被调用cancle方法取消,会抛出CancellationException。注意,FutureTask直接执行run方法,会阻塞等待线程执行完成,如下:

public static void testRun() throws Exception {
    FutureTask<String> future = new FutureTask<>(() -> {
      System.out.println("work...");
      Thread.sleep(5000);
      return "工作完成";
    });
    future.run();
    System.out.println("主线程被阻塞");
    System.out.println(future.get());
}

如果需要异步执行,需要用new Thread()去跑或者通过线程池执行,如下:

  public static void testRun() throws Exception {
    FutureTask<String> future = new FutureTask<>(() -> {
      System.out.println("work...");
      Thread.sleep(5000);
      return "工作完成";
    });
    ExecutorService executor = Executors.newSingleThreadExecutor();
    executor.submit(future);
    System.out.println("主线程不被阻塞");
    System.out.println(future.get());
    System.out.println("主线程阻塞,get等线程返回结果");
  }

2、cancle方法:尝试取消执行此任务,有一个布尔值的参数mayInterruptIfRunning,此参数决定是否可以终止正在执行中的线程。

  • mayInterruptIfRunning为true,可以终止正在执行中的线程,返回true;
    public static void testCancle() throws Exception {
        FutureTask<String> future = new FutureTask<>(() -> {
          System.out.println("work...");
          for (int i = 0; i < 10; i++) {
            Thread.sleep(1000);
            System.out.println(i);
          }
          System.out.println("工作完成!!!!");
          return "工作完成";
        });
        Thread thread = new Thread(future);
        thread.start();
        Thread.sleep(1000);
        System.out.println("取消正在执行的FutureTask");
        //true,会终止正在运行的线程
        System.out.println(future.cancel(true));
        System.out.println(future.isCancelled());
      }

     

  • mayInterruptIfRunning为false,不能终止正在执行中的线程,返回false;
    public static void testCancle() throws Exception {
        FutureTask<String> future = new FutureTask<>(() -> {
          System.out.println("work...");
          for (int i = 0; i < 10; i++) {
            Thread.sleep(1000);
            System.out.println(i);
          }
          System.out.println("工作完成!!!!");
          return "工作完成";
        });
        Thread thread = new Thread(future);
        //false,如果线程已经开始执行,当前任务是不会被终止,但是仍然返回true
        System.out.println("取消还未执行的FutureTask");
        System.out.println(future.cancel(false));
        System.out.println(future.isCancelled());
        thread.start();
    }
  • 如果线程已被cancle,再次cancle将返回false;
     
      public static void testCancle() throws Exception {
        FutureTask<String> future = new FutureTask<>(() -> {
          System.out.println("work...");
          Thread.sleep(5000);
          return "工作完成";
        });
        new Thread(future).start();
        System.out.println("取消正在执行的FutureTask");
        System.out.println(future.cancel(true));
        System.out.println(future.get());
      }

     

3、get方法:等待计算完成,然后检索其结果,这个方法会阻塞主线程,直到run执行完成并返回值。还可以设置最长等待时间,超过将抛出TimeoutException;计算引发异常抛出ExecutionException;当前线程在等待时中断抛出InterruptedException;计算被取消抛出CancellationException。

  public static void testTimeoutException() throws Exception {
    FutureTask<String> future = new FutureTask<>(() -> {
      System.out.println("work...");
      Thread.sleep(5000);
      System.out.println("工作完成!!!!");
      return "工作完成";
    });
    new Thread(future).start();
    System.out.println(future.get(1, TimeUnit.SECONDS));
  }

  public static void testCancellationException() throws Exception {
    FutureTask<String> future = new FutureTask<>(() -> {
      System.out.println("work...");
      Thread.sleep(5000);
      System.out.println("工作完成!!!!");
      return "工作完成";
    });
    new Thread(future).start();
    Thread.sleep(1000);
    System.out.println(future.cancel(true));
    System.out.println(future.get(1, TimeUnit.SECONDS));
  }

  public static void testGetExecutionException() throws Exception {
    FutureTask<String> future = new FutureTask<>(() -> {
      System.out.println("work...");
      throw new Exception("出错啦");
    });
    new Thread(future).start();
    System.out.println(future.get());
  }

  public static void testInterruptedException() throws Exception {
    FutureTask<String> future = new FutureTask<>(() -> {
      System.out.println("work...");
      Thread.sleep(5000);
      return "工作完成";
    });
    Thread thread = new Thread(future);
    thread.start();
    thread.interrupt();
    System.out.println(future.get());
  }

 

### Java `FutureTask` 和 `CompletableFuture` 之间的区别 #### 功能特性差异 `FutureTask` 提供了一种异步获取计算结果的方式,通过实现 `Runnable` 接口来封装可调用的任务。然而,其功能较为有限,仅支持基本的结果检索和取消操作[^1]。 相比之下,`CompletableFuture` 是一种更为强大的工具类,它不仅继承了 `Future` 接口的功能,还实现了 `CompletionStage` 接口,允许开发者构建复杂的异步工作流。这使得 `CompletableFuture` 能够轻松处理多个阶段的操作链,并且提供了丰富的组合方法用于错误处理、回调注册等功能[^2]。 #### 使用灵活性对比 当使用 `FutureTask` 时,通常需要显式创建线程池或管理自己的执行器服务来进行任务提交;而一旦启动,则无法附加任何后续动作除非再次手动编写逻辑代码。 对于 `CompletableFuture` 来说,在设计上更加注重于表达意图而非具体实现细节。这意味着可以通过简洁的方法链接定义一系列按顺序自动触发的行为——无论是成功还是失败情况下的响应措施都可以被优雅地编码出来。 #### 并发模型的支持程度不同 虽然两者都适用于并发编程场景下,但是由于 `CompletableFuture` 内置了许多实用函数用来简化多任务间的协作模式(比如 allOf/anyOf),因此更适合现代应用程序开发中的复杂需求[^4]。 ```java // FutureTask 示例 ExecutorService executor = Executors.newSingleThreadExecutor(); Callable<Integer> task = () -> { Thread.sleep(1000); return 1; }; FutureTask<Integer> futureTask = new FutureTask<>(task); executor.submit(futureTask); try { System.out.println("Result from FutureTask: " + futureTask.get()); } catch (InterruptedException | ExecutionException e) { e.printStackTrace(); } // CompletableFuture 示例 CompletableFuture.supplyAsync(() -> { try { Thread.sleep(1000); } catch (InterruptedException e) { throw new RuntimeException(e); } return 1; }).thenApply(result -> result * 2).thenAccept(System.out::println); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值