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();
}
}

最新文章

  1. EasyUI第一章Application之Basic CRUD(增删改查)
  2. 《DSP using MATLAB》示例Example5.16
  3. js对象/数组深度复制
  4. 使用js和jq去掉左右空格方法
  5. lr_think_time参数化
  6. DNS主从服务,子域授权,view视图,日志系统,压力测试
  7. 如何破解海蜘蛛ISP6.1.5 极其isp运营商 v6.1.5
  8. php29号小结(隔行换色&#183;&#183;&#183;&#183;&#183;&#183;)
  9. live555 源代码简单分析1:主程序
  10. APM代码学习笔记3:执行过程
  11. 依赖于设备的位图(DDB) ,CreateCompatibleBitmap用法
  12. label不换行的问题
  13. 强大的测试管理工具---TestTrack Pro
  14. iOS 字典转模型Model
  15. Average Sleep Time CodeForces - 808B (前缀和)
  16. tensorflow 升级后报错:ImportError: libcudnn.so.6: cannot open shared object file: No such file or directory
  17. dell r420 H310/H810阵列配置教程及常见问题
  18. 深度学习课程笔记(四)Gradient Descent 梯度下降算法
  19. 准备尝试openFrameworks
  20. Awk 从入门到放弃(5)– Awk模式(Pattern)之一

热门文章

  1. 修改SearchBar的取消按钮Cancel为中文
  2. Java+eclipse技巧小总结
  3. Excel催化剂开源第5波-任务窗格在OFFICE2013中新建文档不能同步显示问题解决
  4. Android基础知识复习之打开照相机拍照并获取照片
  5. C语言 结构体字节对齐问题
  6. Elasticsearch 7.x Nested 嵌套类型查询 | ES 干货
  7. [Github]watch和star的区别
  8. Flume+Kafka收集Docker容器内分布式日志应用实践
  9. HTTP_5_通信数据转发程序:代理、网关、隧道
  10. 一份关于.NET Core云原生采用情况调查