FutureTask 源码分析,这个类的原理与我分析android当中的FutureTask类差不多[http://www.cnblogs.com/daxin/p/3802392.html]

public class FutureTask<V> implements RunnableFuture<V> {
/** 所有的方法全部委托sync */
private final Sync sync; public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
sync = new Sync(callable);
} public FutureTask(Runnable runnable, V result) {
sync = new Sync(Executors.callable(runnable, result));
} public boolean isCancelled() {
return sync.innerIsCancelled();
} public boolean isDone() {
return sync.innerIsDone();
} public boolean cancel(boolean mayInterruptIfRunning) {
return sync.innerCancel(mayInterruptIfRunning);
} public V get() throws InterruptedException, ExecutionException {
return sync.innerGet();
} public V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {
return sync.innerGet(unit.toNanos(timeout));
} protected void done() { } protected void set(V v) {
sync.innerSet(v);
} protected void setException(Throwable t) {
sync.innerSetException(t);
} public void run() {
sync.innerRun();
} protected boolean runAndReset() {
return sync.innerRunAndReset();
} private final class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = -7828117401763700385L; /** State value representing that task is ready to run */
/** 代表起始状态 */
private static final int READY = 0;
/** State value representing that task is running */
/** 代表正在运行中状态 */
private static final int RUNNING = 1;
/** State value representing that task ran */
/** 代表运行完成的状态 */
private static final int RAN = 2;
/** State value representing that task was cancelled */
/** 代表被取消的状态 */
private static final int CANCELLED = 4; /** The underlying callable */
private final Callable<V> callable;
/** The result to return from get() */
private V result;
/** The exception to throw from get() */
private Throwable exception; /**
* The thread running task. When nulled after set/cancel, this
* indicates that the results are accessible. Must be
* volatile, to ensure visibility upon completion.
*/
private volatile Thread runner; Sync(Callable<V> callable) {
this.callable = callable;
} /**
* 判断是否完成或者是否取消
* 传入0或者1 都返回0 说明任务没有完成 也没有取消
*/
private boolean ranOrCancelled(int state) {
return (state & (RAN | CANCELLED)) != 0;
} /**
* AbstractQueuedSynchronizer的模板方法
* 返回1可以获取锁 返回-1说明获取锁失败
* 调用innerIsDone 返回TRUE 说明任务已经执行完毕
* 返回FALSE 说明任务没有执行完毕
*/
protected int tryAcquireShared(int ignore) {
return innerIsDone() ? 1 : -1;
} /**
* 释放锁 将执行当前任务的线程设置为null
*/
protected boolean tryReleaseShared(int ignore) {
runner = null;
return true;
} //判断任务是否被取消
boolean innerIsCancelled() {
return getState() == CANCELLED;
} //判断任务是否完成(取消也算完成)
boolean innerIsDone() {
return ranOrCancelled(getState()) && runner == null;
} //获取结果
V innerGet() throws InterruptedException, ExecutionException {
//首先调用AbstractQueuedSynchronizer的方法,这个方法会调用子类方法tryAcquireShared 上面有讲
//如果当前任务已经完成,那么当前线程可以向下运行,否则把当前线程加入队列阻塞.
acquireSharedInterruptibly(0);
//判断状态 如果取消了就抛CancellationException异常.
if (getState() == CANCELLED)
throw new CancellationException();
//如果任务执行过程中出现异常,这里包装一下抛出ExecutionException.
if (exception != null)
throw new ExecutionException(exception);
return result;
} //获取结果
V innerGet(long nanosTimeout) throws InterruptedException, ExecutionException, TimeoutException {
//调用AbstractQueuedSynchronizer里的方法
// return tryAcquireShared(arg) >= 0 ||doAcquireSharedNanos(arg, nanosTimeout);
// 首先tryAcquireShared调用它获取锁,也就是看任务完事没,如果任务完事了就返回TRUE,那么执行逻辑同上。
// 如果获取不到锁,那么就阻塞当前线程给定的时间,如果时间到了再次任务还没完成则抛出异常。
if (!tryAcquireSharedNanos(0, nanosTimeout))
throw new TimeoutException();
if (getState() == CANCELLED)
throw new CancellationException();
if (exception != null)
throw new ExecutionException(exception);
return result;
} void innerSet(V v) {
for (;;) {
int s = getState();
if (s == RAN)
return;
if (s == CANCELLED) {
// aggressively release to set runner to null,
// in case we are racing with a cancel request
// that will try to interrupt runner
releaseShared(0);
return;
}
//正常完成 设置状态为RAN
if (compareAndSetState(s, RAN)) {
result = v;
releaseShared(0);
done(); //通知子类
return;
}
}
} void innerSetException(Throwable t) {
for (;;) {
int s = getState();
if (s == RAN)
return;
if (s == CANCELLED) {
// aggressively release to set runner to null,
// in case we are racing with a cancel request
// that will try to interrupt runner
releaseShared(0);
return;
}
//设置异常
if (compareAndSetState(s, RAN)) {
exception = t;
releaseShared(0);
done();//通知子类
return;
}
}
} //取消任务
boolean innerCancel(boolean mayInterruptIfRunning) {
for (;;) {
int s = getState();
//如果任务已经结束,则返回FALSE
if (ranOrCancelled(s))
return false;
//设置任务的状态为CANCELLED
if (compareAndSetState(s, CANCELLED))
break;
}
//如果参数mayInterruptIfRunning=TRUE,那么设置线程的终端状态
if (mayInterruptIfRunning) {
Thread r = runner;
if (r != null)
r.interrupt();
}
//释放锁
releaseShared(0);
//调用子类方法,通知状态改变
done();
return true;
} void innerRun() {
//如果任务不是初始状态则直接结束
if (!compareAndSetState(READY, RUNNING))
return; runner = Thread.currentThread();
if (getState() == RUNNING) { // recheck after setting thread
V result;
try {
result = callable.call();
} catch (Throwable ex) {
//我们写的任务方法里如果出现异常则调用setException
setException(ex);
return;
}
//设置结果
set(result);
} else {
//释放锁
releaseShared(0); // cancel
}
} boolean innerRunAndReset() {
if (!compareAndSetState(READY, RUNNING))
return false;
try {
runner = Thread.currentThread();
if (getState() == RUNNING)
callable.call(); // don't set result
runner = null;
return compareAndSetState(RUNNING, READY);
} catch (Throwable ex) {
setException(ex);
return false;
}
}
}
}

FutureTask 源码分析的更多相关文章

  1. Java并发编程笔记之FutureTask源码分析

    FutureTask可用于异步获取执行结果或取消执行任务的场景.通过传入Runnable或者Callable的任务给FutureTask,直接调用其run方法或者放入线程池执行,之后可以在外部通过Fu ...

  2. 并发编程—— FutureTask 源码分析

    1. 前言 当我们在 Java 中使用异步编程的时候,大部分时候,我们都会使用 Future,并且使用线程池的 submit 方法提交一个 Callable 对象.然后调用 Future 的 get ...

  3. FutureTask源码分析

    1. 常量和变量 private volatile int state; // 任务状态 private static final int NEW = 0; private static final ...

  4. FutureTask源码分析(JDK7)

    总览 A cancellable asynchronous computation. This class provides a base implementation of {@link Futur ...

  5. JUC源码分析-线程池篇(二)FutureTask

    JUC源码分析-线程池篇(二)FutureTask JDK5 之后提供了 Callable 和 Future 接口,通过它们就可以在任务执行完毕之后得到任务的执行结果.本文从源代码角度分析下具体的实现 ...

  6. Java 多线程(五)—— 线程池基础 之 FutureTask源码解析

    FutureTask是一个支持取消行为的异步任务执行器.该类实现了Future接口的方法. 如: 取消任务执行 查询任务是否执行完成 获取任务执行结果(”get“任务必须得执行完成才能获取结果,否则会 ...

  7. Java异步编程——深入源码分析FutureTask

    Java的异步编程是一项非常常用的多线程技术. 之前通过源码详细分析了ThreadPoolExecutor<你真的懂ThreadPoolExecutor线程池技术吗?看了源码你会有全新的认识&g ...

  8. 线程之Callable、Future 和FutureTask使用及源码分析

    一.Callable 我们知道启动线程有以下两种方式(jdk源码注释中官方定义只有两种启动方式,callable不算线程启动方式) 原文链接:http://www.studyshare.cn/blog ...

  9. android高级---->AsyncTask的源码分析

    在Android中实现异步任务机制有两种方式,Handler和AsyncTask,它在子线程更新UI的例子可以参见我的博客(android基础---->子线程更新UI).今天我们通过一个小的案例 ...

随机推荐

  1. Redis命令汇总

    设置服务后台启动 cd /usr/local/redisview redis.conf 将daemonize no改为 daemonize yes保存退出 启动:./reids-server redi ...

  2. android数据存取的四种方式

    Android系统下有四种数据的存在形式,分别是SQLite,SharePreference,File,ContentProvider.一:特性介绍:SQLite:对于大多数开发者而言,这应该是大家非 ...

  3. 温故而知新 Vue 原来也有this.$forceUpdate();

    由于一些嵌套特别深的数据,导致数据更新了.UI没有更新(连深度监听都没有监听到),我捉摸着有没有和react一样的立即更新UI的API呢 this.forceUpdate()呢?结果还真有: this ...

  4. 使用 sqlyog 导入导出数据显示 lost connection to mysql server during query

    mysql中经常需要备份数据,在使用 sqlyog 进行备份数据库为转储文件,然后在其他数据库中导入发生 lost connection 经过查询大量资料是数据库配置的 max_allowed_pac ...

  5. django class-based view 考古

    django 中的view中进化史: 1.在“天地初开”的时候django中的view是通过函数来定义的.函数接收一个request并以一个response作为返回: 对于这个request是通过po ...

  6. js评价五星

    js评价五星 1.图片(star.png): 2.图片和html文件在同级目录 <html> <head> <script src="http://libs.b ...

  7. javaweb可部署目录结构

    webApp //项目名称 -META-INF --MANIFEST.MF -WEB-INF --classes   //编译class文件 --lib  //依赖jar --web.xml -ind ...

  8. jQuery添加/改变/移除CSS类

    转自:http://www.jbxue.com/article/24589.html 在jquery中用到removeClass移除CSS类.addClass添加CSS类.toggleClass添加或 ...

  9. python代码制作configure文件

    在lua中,一直用lua作为config文件,或承载数据的文件 - 好处是lua本身就很好阅读,然后无需额外写解析的代码,还支持在configure文件中读环境变量,条件判断等. 在lua中通过loa ...

  10. 将redis作为windows服务安装

    1,下载redis并解压到一个目录下,然后切换到该目录下,也就是redis-server.exe文件所在的目录 2,在cmd下执行 redis-server --service-install red ...