自定义FutureTask实现
2019-08-16 12:21:23来源:博客园 阅读 ()
自定义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
如有疑问请与原作者联系
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
- DES/3DES/AES 三种对称加密算法实现 2020-06-11
- SpringBoot + Vue + ElementUI 实现后台管理系统模板 -- 后 2020-06-10
- Spring Boot 实现定时任务的 4 种方式 2020-06-10
- JSP+SSH+Mysql+DBCP实现的租车系统 2020-06-09
- Java实现的三种字符串反转 2020-06-09
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash