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

自定义FutureTask实现的更多相关文章
- Java FutureTask理解
尊敬原创作者,转载请注明出处: http://blog.csdn.net/gemmem/article/details/8956703 FutureTask是为了弥补Thread的不足而设计的,它可以 ...
- [转载] java多线程学习-java.util.concurrent详解(二)Semaphore/FutureTask/Exchanger
转载自http://janeky.iteye.com/blog/770393 ------------------------------------------------------------- ...
- java中Future与FutureTask使用与分析
Future与FutureTask都是用于获取线程执行的返回结果.下面我们就对两者之间的关系与使用进行一个大致的介绍与分析 一.Future与FutureTask介绍: Future位于java.ut ...
- FutureTask简单实战
FutureTask是什么? 线程池的实现核心之一是FutureTask.在提交任务时,用户实现的Callable实例task会被包装为FutureTask实例ftask:提交后任务异步执行,无需用户 ...
- 《java并发编程实战》读书笔记11--构建自定义的同步工具,条件队列,Condition,AQS
第14章 构建自定义的同步工具 本章将介绍实现状态依赖性的各种选择,以及在使用平台提供的状态依赖机制时需要遵守的各项规则. 14.1 状态依赖性的管理 对于并发对象上依赖状态的方法,虽然有时候在前提条 ...
- Flume自定义拦截器(Interceptors)或自带拦截器时的一些经验技巧总结(图文详解)
不多说,直接上干货! 一.自定义拦截器类型必须是:类全名$内部类名,其实就是内部类名称 如:zhouls.bigdata.MySearchAndReplaceInterceptor$Builder 二 ...
- SpringCache自定义过期时间及自动刷新
背景前提 阅读说明(十分重要) 对于Cache和SpringCache原理不太清楚的朋友,可以看我之前写的文章:Springboot中的缓存Cache和CacheManager原理介绍 能关注Spri ...
- Java线程之FutureTask
简述 FutureTask是Future接口的实现类,并提供了可取消的异步处理的功能,它包含了启动和取消(start and cancel)任务的方法,同时也包含了可以返回FutureTask状态(c ...
- 线程池续:你必须要知道的线程池submit()实现原理之FutureTask!
前言 上一篇内容写了Java中线程池的实现原理及源码分析,说好的是实实在在的大满足,想通过一篇文章让大家对线程池有个透彻的了解,但是文章写完总觉得还缺点什么? 上篇文章只提到线程提交的execute( ...
随机推荐
- 关于在使用scrapy-redis分布式踩过的那些坑:
自己的案列:win7上安装ubuntu (win7作为slaver,ubuntu作为master ) 修改配置文件redis.conf 1)打开配置文件把下面对应的注释掉 # bind 127.0.0 ...
- Salesforce Admin篇(二) Report
针对salesforce系统也好,针对其他的平台系统也好,对于business user的需求以及疑问,数据往往决定了答案.业务人员提出了某些疑问,管理员需要根据需求的分析转换成数据的分析及过滤从而反 ...
- 好用的在线画图工具processon
ProcessOn是一款基于SaaS的前沿.高效线上作图工具,它将Visio.Xmind等专业作图工具搬到了"云端" 注册链接:https://www.processon.com/ ...
- Object.keys使用整理
一.语法 Object.keys(obj) 参数:要返回其枚举自身属性的对象 返回值:一个表示给定对象的所有可枚举属性的字符串数组 二.处理对象,返回可枚举的属性数组 let person = { n ...
- MySQL Explain查看执行计划
这篇博客写的还是蛮全的 http://www.cnblogs.com/songwenjie/p/9409852.html 在执行SQL的时候,经常有些SQL未正确使用到索引,导致程序变慢,通过使用ex ...
- 剑指offer第二版-5.替换空格
面试题5:替换空格 题目要求: 实现一个函数,把字符串中的每个空格都替换成“%20”,已知原位置后面有足够的空余位置,要求改替换过程发生在原来的位置上. 思路: 首先遍历字符串求出串中空格的数量,求出 ...
- JQuery学习笔记(3)——节点操作 节点查找
插入节点 内部插入 所谓的内部插入,就是指在节点里面的插入,而外部插入,则是在节点外面插入. append() prepend() appendTo() prependTo() append和prep ...
- C# 与 JS 之间传值在 cshtml页面中
@{ string It = "sss"; ; } @functions{ string Mod = "ajssaioi"; public string Itm ...
- 在dotnet core实现类似crontab的定时任务
前段需要在业务中实现某些时间段的简单定时任务,类似crontab的调度,因为业务会放在docker中,所以不想用直接用crontab,在网上搜了一下,发现一个开源的实现 Pomelo.AspNetCo ...
- Python3安装与使用urllib2包之小坑
Python3 安装urllib2包之小坑 Python3.6.6或者说python3.x找不到urllib2语法问题修改之后,会报一个没有安装urllib2的包的错误. 通过pip install ...