自定义FutureTask实现

FutureTask

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

代码示例:

public class ThreadTest {

  public static void main(String[] args) throws Exception {

    Callable<String> myCallable = new MyCallableThread();
    FutureTask<String> futureTask = new FutureTask<>(myCallable);
    Thread myCallableThread = new Thread(futureTask);
    myCallableThread.setName("MyThread-implements-Callable-test");
    myCallableThread.start();
    System.out.println("Run by Thread:" + futureTask.get());

    //通过线程池执行
    ExecutorService executorService = Executors.newCachedThreadPool();
    executorService.submit(futureTask);
    executorService.shutdown();
    System.out.println("Run by ExecutorService:" + futureTask.get());
  }
}

class MyCallableThread implements Callable<String> {

  @Override
  public String call() throws Exception {
    return Thread.currentThread().getName();
  }
}

实现一个自己的FutureTask

根据FutureTask核心原理,要实现一个FutureTask必须满足以下方面:

  • 需要泛型定义用以返回结果类型
  • 需要一个callable对象,在构造方法中传入
  • 需要实现runnable接口,在run方法中实现具体结果计算
  • 需要一个公开的get方法来获取结果
  • 如果线程没有执行完,则调用get方法的线程需要进入等待队列
  • 需要一个字段记录线程执行的状态
  • 需要一个等待队列存储等待结果的线程

代码示例:

/**
 * 1. 泛型定义
 * 2. 构造方法 callable
 * 3. 实现了runnable
 * 4. get方法返回callable执行结果
 * 5. get方法有阻塞的效果(未执行结束的话)
 */
public class MyFutureTask<T> implements Runnable {

  // 程序执行的结果
  private T result;

  // 要执行的任务
  private Callable<T> callable;

  // 任务运行的状态
  private volatile int state = NEW;

  // 任务运行的状态值
  private static final int NEW = 0;
  private static final int RUNNING = 1;
  private static final int FINISHED = 2;

  // 获取结果的线程等待队列
  LinkedBlockingQueue<Thread> waiters = new LinkedBlockingQueue<>(100);

  // 执行当前FutureTask的线程,用CAS进行争抢
  AtomicReference<Thread> runner = new AtomicReference<>();

  public MyFutureTask(Callable<T> task) {
    this.callable = task;
  }

  @Override
  public void run() {
    // 判断当前对象的状态,如果是New且抢锁成功就执行
    if (state != NEW || !runner.compareAndSet(null, Thread.currentThread())) return;
    state = RUNNING;
    try {
      result = callable.call();
    } catch (Exception e) {
      e.printStackTrace();
    } finally {
      state = FINISHED;
    }

    // 方法执行完,唤醒所有线程
    while (true) {
      Thread waiterThread = waiters.poll();
      if (waiterThread == null) break;
      LockSupport.unpark(waiterThread);
    }
  }

  public T get() {
    // 如果状态不是FINISHED,则进入等待队列
    if (state != FINISHED) {
      waiters.offer(Thread.currentThread());
    }
    while (state != FINISHED) {
      LockSupport.park();
    }
    return result;
  }
}

// MyFutureTask 测试
public class FutureTaskTest {
  public static void main(String[] args) {

    Callable<String> myCallable = new MyCallableThread();
    MyFutureTask<String> futureTask = new MyFutureTask<>(myCallable);
    Thread myCallableThread = new Thread(futureTask);
    myCallableThread.setName("MyFutureTask-test");
    myCallableThread.start();
    System.out.println("Run by Thread:" + futureTask.get());
  }
}

class MyCallableThread implements Callable<String> {

  @Override
  public String call() throws Exception {
    return Thread.currentThread().getName();
  }
}

转载于:https://www.cnblogs.com/coding-diary/p/11336686.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
FutureTask是Java中Executor框架提供的一个实用工具类,用来表示一个异步计算的结果,其中包含了对任务的执行状态以及返回结果的控制。FutureTask实现原理主要包括以下几个方面: 1. FutureTask内部有一个volatile修饰的state字段,用于表示任务的执行状态。初始状态为NEW,表示任务还未开始执行;运行状态为RUNNING,表示任务正在执行中;完成状态为COMPLETING,表示任务已经执行完成但还未获取结果;NORMAL,表示任务正常执行完成;异常状态为EXCEPTIONAL,表示任务执行过程中发生异常。 2. FutureTask实现了Runnable和Future接口。在任务执行的过程中,通过重写Runnable接口的run方法来执行具体的任务逻辑,并将任务的结果保存在result字段中。因为实现Future接口,所以FutureTask可以通过get方法来获取任务的执行结果,如果任务还未执行完成,则get方法会阻塞等待任务完成。 3. FutureTask使用AQS(AbstractQueuedSynchronizer)来实现任务的执行控制。AQS是Java并发包中用于实现锁和同步器的基础类,通过实现AQS的子类Sync,来控制任务的执行和获取结果的过程。在任务执行过程中,通过CAS操作来更新任务的执行状态,确保只有一个线程能够成功获取任务的结果。 4. FutureTask还支持任务的取消操作。在调用cancel方法时,会尝试将任务的执行状态设置为CANCELLED,如果设置成功,则任务会被标记为已取消。取消任务时,如果任务已经在执行过程中,则会中断该任务的执行线程。 总之,FutureTask通过内部的状态管理、AQS实现控制、Runnable和Future接口的实现实现了异步任务的执行控制和结果获取功能,为多线程编程提供了更强大和便捷的支持。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值