Android系统框架_安卓startactivity

Android (4) 2024-07-09 19:23

Hi,大家好,我是编程小6,很荣幸遇见你,我把这些年在开发过程中遇到的问题或想法写出来,今天说一说
Android系统框架_安卓startactivity,希望能够帮助你!!!。

在研究AsyncTask源代码的时候发现它的内部使用了FutureTask、Future、Callable类,然后就学习了一下。

1.Runnable、Callable和Future
Executor框架使用Runnable作为其基本的任务表示形式。Runnable是一种有很大局限的抽象,它不能返回一个值或抛出一个受检查的异常。
Runnable接口:
public interface Runnable {

public abstract void run();
}
由于run()方法返回值为void类型,所以在执行完任务之后无法返回任何结果。

许多任务实际上都存在延迟的计算,对于这些任务,Callable是一种更好的抽象:它会返回一个值,并可能抛出一个异常。
Callable接口:
public interface Callable< V> {

V call() throws Exception;
}
可以看到,这是一个泛型接口,call()函数返回的类型就是传递进来的V类型。

Runnable和Callable描述的都是抽象的计算任务。这些任务通常是有生命周期的。Executor执行的任务有4个生命周期阶段:创建、提交、开始和完成。由于有些任务可能要执行很长时间,因此通常希望可以取消这些任务。在Executor框架中,已提交但尚未开始的任务可以取消,对于已经开始执行的任务,只有当它们响应中断时才能取消。

Future是一个接口,表示一个任务的生命周期,并提供了方法来判断是否已经完成或取消,以及获取任务的结果和取消任务等。
Future接口:
public interface Future< V> {

boolean cancel(boolean
mayInterruptIfRunning);
boolean isCancelled();
boolean isDone();
V get() throws InterruptedException, ExecutionException;
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
}
在Future接口中声明了5个方法,下面依次解释每个方法的作用:
①cancel方法用来取消任务,如果取消任务成功则返回true,如果取消任务失败则返回false。参数mayInterruptIfRunning表示是否允许取消正在执行却没有执行完毕的任务,如果设置true,则表示可以取消正在执行过程中的任务。如果任务已经完成,则无论mayInterruptIfRunning为true还是false,此方法肯定返回false,即如果取消已经完成的任务会返回false;如果任务正在执行,若mayInterruptIfRunning设置为true,则返回true,若mayInterruptIfRunning设置为false,则返回false;如果任务还没有执行,则无论mayInterruptIfRunning为true还是false,肯定返回true。
②isCancelled方法表示任务是否被取消成功,如果在任务正常完成前被取消成功,则返回 true。
③isDone方法表示任务是否已经完成,若任务完成,则返回true;
④get()方法用来获取执行结果,这个方法会产生阻塞,会一直等到任务执行完毕才返回;
⑤get(long timeout, TimeUnit unit)用来获取执行结果,如果在指定时间内,还没获取到结果,就直接返回null。
也就是说实际上Future提供了三种功能:
①判断任务是否完成;
②中断任务;
③获取任务执行结果。

Future只是一个接口,无法直接创建对象,因此有了FutureTask。

2.FutureTask
FutureTask是一个用来执行异步任务的类,同时当程序执行完成之后还会返回运算的结果。
我们之前经常使用Thread+Runnable来执行异步任务的,但是使用这种方式不能获取到执行的结果。FutureTask解决了这个问题。

FutureTask用法:
public class FutureTaskActivity extends Activity implements View.OnClickListener {


//创建一个实现了Callable接口并且在call()方法中做耗时操作的类
class WorkTask implements Callable< Integer> {

@Override
public Integer call() throws Exception {

//使用线程sleep来模拟耗时的操作
Thread.sleep(5000);
//将执行的结果返回出去
return 1000;
}
}

private void executeTask() {

//创建一个实现了Callable的类的对象,并且当作参数传入到FutureTask中
WorkTask workTask = new WorkTask();
FutureTask< Integer> futureTask = new FutureTask< Integer>(workTask) {

@Override
protected void done() {

try {

//该方法是在线程运行结束或者被取消后回调的,用get方法获取call方法中返回的结果
int result = get();
Log.i(“LOH”, “result…” + result);
Thread.currentThread().getName();
} catch (InterruptedException e) {

e.printStackTrace();
} catch (ExecutionException e) {

e.printStackTrace();
}
}
};
//将FutureTask作为参数传入到Thread函数中执行
Thread thread = new Thread(futureTask);
//启动线程执行任务
thread.start();
}
}
其实FutureTask的使用跟Runnable的使用差不多的,只是多出了一个用来实现Callable接口的类作为参数传入到 FutureTask中,并且能监听线程执行完成。

总结一下使用线程来执行异步任务的几种方式:
①使用new Thread(new Runnable()).start()的方法来执行异步任务,也就是说将实现Runnable接口的类当作参数传入到Thread 类中,然后使用thread.start来启动线程执行
②通过继承Thread类并且重写该类的run方法,在该方法中执行耗时的操作,同样也是使用 Thread.start()来启动线程执行
③使用线程池来执行实现Runnable接口的类,这样子也可以达到执行异步任务的目的。
④AsyncTask
⑤HandlerThread
⑥IntentService
⑦FutureTask
其实用这些方法实现异步任务的本质是实现 Runnable() 接口,所以FutureTask也是实现了该接口的,不然就无法执行异步任务的。

3.FutureTask源码解析
先来看下FutureTask的实现:
public class FutureTask< V> implements RunnableFuture< V> { }
FutureTask类实现了RunnableFuture接口。

再来看RunnableFuture接口:
public interface RunnableFuture< V> extends Runnable, Future< V> {

void run();
}
RunnableFuture继承了Runnable和Future接口,而FutureTask实现了RunnableFuture接口。

首先我们通过一个类的关系图来看看这几个类之间的关系图:
Android系统框架_安卓startactivity_https://bianchenghao6.com/blog_Android_第1张
FutureTask是一个可取消的异步计算,它实现了Future的基本方法,提供start、cancel操作,可以查询计算是否已经完成,并且可以获取计算的结果。结果只可以在计算完成之后获取,当计算没有完成的时候get方法会阻塞。一旦计算已经完成, 那么计算就不能再次启动或是取消。
一个FutureTask可以用来包装一个Callable或是一个Runnable对象(对应FutureTask的两个构造方法)。因为FurtureTask实现了Runnable方法,所以FutureTask可以提交(submit)给一个Excutor执行; 它同时实现了Callable, 所以也可以作为Future得到Callable的返回值。

FutureTask有两个很重要的属性分别是state和runner, FutureTask之所以支持cancel操作,也是因为这两个属性。
其中state为枚举值:
private volatile int state; // 注意volatile关键字

//在构建FutureTask时设置,同时也表示内部成员callable已成功赋值,一直到子线程完成FutureTask中的run()
private static final int NEW = 0;

//子线程在处理task时设定的中间状态,处于该状态时,说明子线程正准备设置result
private static final int COMPLETING = 1;

//当设置result结果完成后,FutureTask处于该状态,代表过程结果,该状态为最终状态final state(正确完成的最终状态)
private static final int NORMAL = 2;

//同上,只不过task执行过程出现异常,此时结果设值为exception,也是final state
private static final int EXCEPTIONAL = 3;

//也是final state, 表明task被cancel(task还没有执行就被cancel的状态)
private static final int CANCELLED = 4;

//中间状态,task运行过程中被interrupt时,设置的中间状态
private static final int INTERRUPTING = 5;

// final state, 中断完毕的最终状态
private static final int INTERRUPTED = 6;

state初始化为NEW,只有在set、setException和cancel方法中state才可以转变为终态。在任务完成期间,state的值可能为COMPLETING或INTERRUPTING。
state有四种可能的状态转换:
NEW -> COMPLETING -> NORMAL
NEW -> COMPLETING -> EXCEPTIONAL
NEW -> CANCELLED
NEW -> INTERRUPTING -> INTERRUPTED

其他成员变量:
private Callable< V> callable; // 具体run运行时会调用其方法call(),并获得结果,结束时置为null
private Object outcome; // 返回的结果或异常,没必要为volatile,因为其是伴随state进行读写,而state是FutureTask的主导因素。
private volatile Thread runner; //具体的子线程
//Treiber stack of waiting threads
private volatile WaitNode waiters;

下面分析下Task的状态变化,也就是一个任务的生命周期:
创建一个FutureTask,首先调用构造方法。FutureTask有两个构造方法:
①直接传入一个Callable实现类
public FutureTask(Callable< V> callable){

if(Callable = = null)
throw new NullPointException();
this.callable = callable;
this.state = NEW;
}
②传入一个Runnable和一个预设结果
public FutureTask(Runnable runnable, V result) {

this.callable = Executors.callable(runnable, result);
this.state = NEW;
}
此时将state设置为初始态NEW。
这里注意第二个构造方法里,Runnable是怎样转换为Callable的,看下this.callable = Executors.callable(runnable, result); 调用Executors.callable:
public static < T> Callable< T> callable(Runnable task, T result) {

if (task == null)
throw new NullPointerException();
return new RunnableAdapter< T>(task, result);
}
static final class RunnableAdapter< T> implements Callable< T> {

final Runnable task;
final T result;
RunnableAdapter(Runnable task, T result) {

this.task = task;
this.result = result;
}
public T call() {

task.run();
//把传入的值直接返回
return result;
}
}
其实就是通过Callable的call方法调用Runnable的run方法,把传入的 T result 作为callable的返回结果直接返回了,所以FutureTask(Runnable runnable, V result)得到的只是预设的结果,Runnable并不会得到执行的结果。如果不需要预设的返回结果,可以这样初始化:
FutureTask<?> f = new FutureTask< Void>(runnable, null);

当创建完一个Task通常会提交给Executors来执行,当然也可以使用Thread来执行,Thread的start()方法会调用Task的run()方法。那么,看看它的源码:
public class FutureTask< V> implements RunnableFuture< V> {


public void run() {

//如果当前线程的状态不是原始状态,或者当前线程已经赋值成功,则不用重复执行该逻辑
if (state != NEW ||
!U.compareAndSwapObject(this, RUNNER, null, Thread.currentThread()))
return;
try {

//将传进来的callable对象赋值给一个临时变量
Callable< V> c = callable;
//判断传入进来的callable对象不为空并且线程状态也是新建的
if (c != null && state == NEW) {

V result;
boolean ran;
try {

//在run方法中执行的call()方法,然后call()返回一个泛型类型的返回值 ,这种通过实现接口的方法在我们平时中是很常见的吧
result = c.call();
ran = true;
//在定义call方法的时候抛出异常,然后这里捕捉异常进行处理,因为我们在call方法中写代码难免会有异常问题的
} catch (Throwable ex) {

result = null;
ran = false;
setException(ex);
}
//如果call方法中不跑出异常的话,则通过set()方法将结果保存起来,该set()方法其实也是Future接口定义的方法
if (ran)
set(result);
}
} finally {

runner = null;
int s = state;
//如果当前的状态不是
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
}
}

}
state刚开始值为NEW,如果不等于NEW,说明任务状态已经改变(说明它走了上面4中可能变化的一种)。如果状态是NEW,判断成员变量runner是否为null,如果runner的值为null,则把当前执行任务的线程赋值给runner, 如果成功,则返回true;如果runner不为null, 或者赋值失败,返回false,则说明已经赋过值了,不用重复操作。
call()方法就是在run()方法中执行的。
boolean ran是判断Callable中执行耗时操作是否有异常,是否成功的标识。如果异常了,result会置空,ran = false; 然后执行setException(ex);操作。

这里
!UNSAFE.compareAndSwapObject(this, runnerOffset, null, Thread.currentThread())
语义相当于
if (this.runner == null ){

this.runner = Thread.currentThread();
}
使用compareAndSwap能够保证原子性,保证多个线程同时提交一个futureTask时,确保该futureTask的run只被调用一次。如果想运行多次,使用runAndReset方法。

接着开始执行任务,如果要执行的任务不为空,并且state为New就执行,可以看到这里调用了Callable的call方法。如果执行成功则set结果,如果出现异常则setException。最后把runner设为null。

接着看下set方法:
protected void set(V v) {

if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {

outcome = v;
UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
finishCompletion();
}
}
如果现在的状态是NEW就把状态设置成COMPLETING,然后设置成NORMAL。这个执行流程的状态变化就是: NEW->COMPLETING->NORMAL。

如果异常了,result会置空,ran = false; 然后执行 setException(ex);操作,看看代码 :
protected void setException(Throwable t) {

if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING)) {

outcome = t;
U.putOrderedInt(this, STATE, EXCEPTIONAL); // final state
finishCompletion();
}
}
第一行是把成员变量state的值由NEW变为COMPLETING,然后把异常赋值给outcome,赋值成功后,把state的值,由COMPLETING变为EXCEPTION,然后执行finishCompletion()方法,此方法是一个循环执行。
private void finishCompletion() {

for (WaitNode q; (q = waiters) != null;) {

//根据寻找内存地址的方式来修改属性在内存中的值,将该waiters对象置为null
if (U.compareAndSwapObject(this, WAITERS, q, null)) {

for ( ; ; ) {

Thread t = q.thread;
if (t != null) {

q.thread = null;
LockSupport.unpark(t);
}
WaitNode next = q.next;
if (next == null)
break;
q.next = null; // unlink to help gc
q = next;
}
break;
}
}
//回调Future接口的方法,标识程序正常的结束了,我们需要重写该方法.
done();
//特别需要注意的是需要将该接口变量置为空,防止出现因为引用问题导致内存泄漏
callable = null; // to reduce footprint,
}
当执行到该方法的时候,就标识程序正常的运行结束了,首先会将所有等待的线程全部唤醒,因为在执行FutureTask任务的时候调用get()方法是阻塞的,因为call()方法都还没有执行完成,这个时候你是获取不到任何结果的,所以会将当前调用get()方法的线程阻塞等待,直到调用finishCompletion()方法来解除线程阻塞,最后调用done()方法,这个时候我们就可以在该结束方法中执行我们想要的逻辑了;从代码中我们可以看出done()方法其实也还是运行在子线程的,所以我们不可以在done()方法中更新UI,还是需要Handler来发送消息的。
在线程全部执行结束之后,我们就可以在done()方法通过调用get()方法来获取最后执行的结果了,也就是刚刚在set()方法中看到的outcome的值。
public V get() throws InterruptedException, ExecutionException {

int s = state;
if (s <= COMPLETING)
s = awaitDone(false, 0L);
return report(s);
}
首先判断FutureTask的状态是否为完成状态,如果是完成状态,说明已经执行过set或setException方法,之前在调用set()方法时通过寻址(根据内存地址的偏移量)的方式修改过了state的值为NORMAL了,所以NORMAL大于COMPLETING,最后直接调用report()方法,最后直接通过return x 来返回结果。
private V report(int s) throws ExecutionException {

Object x = outcome;
if (s==NORMAL)
return (V)x;
if (s >= CANCELLED)
throw new CancellationException();
throw new ExecutionException((Throwable)x);
}
可以看到,如果FutureTask的状态是NORMAL, 即正确执行了set方法,get方法直接返回处理的结果, 如果是取消状态,即执行了setException,则抛出CancellationException异常。

我们通过调用Future接口的isDone()来判断程序是否结束,可以直接根据state的状态判断是否是新创建的,该类的线程有7种不同的状态,只要状态切换成其中的一种就可以说程序结束了。
public boolean isDone() {

return state != NEW;
}
只要状态值大于CANCELLED(4),也就是用户主动调用cancel()方法,不管是主动中断线程还是其他的方式都属于取消的操作的。
public boolean isCancelled() {

return state >= CANCELLED;
}
当程序里面的FutureTask未执行完成的时候get()方法会一直阻塞调用该方法的线程,直到FutureTask里面的任务执行完才会解除阻塞。所以get()方法是一个阻塞式的去获取结果的,从上面的get()方法的代码中我们可以得出
当状态还是NEW的时候,会调用awaitDone(false ,0)方法。
private int awaitDone(boolean timed, long nanos) throws InterruptedException {

long startTime = 0L; // Special value 0L means not yet parked
WaitNode q = null;
boolean queued = false;
for ( ; ; ) {

int s = state;
if (s > COMPLETING) {

if (q != null)
q.thread = null;
return s;
} else if (s==COMPLETING)
// We may have already promised (via isDone) that we are done, so never return empty-handed or throw InterruptedException
Thread.yield();
else if (Thread.interrupted()) {

removeWaiter(q);
throw new InterruptedException();
} else if (q == null) {

if (timed && nanos <= 0L)
return s;
q = new WaitNode();
} else if (!queued)
queued = U.compareAndSwapObject(this, WAITERS, q.next = waiters, q);
else if (timed) {


} else
LockSupport.park(this);
}
}
awaitDone方法可以看成是不断轮询查看FutureTask的状态。在get阻塞期间:
①如果执行get的线程被中断,则移除FutureTask的所有阻塞队列中的线程(waiters),并抛出中断异常;
②如果FutureTask的状态转换为完成状态(正常完成或取消),则返回完成状态;
③如果FutureTask的状态变为COMPLETING, 则说明正在set结果,此时让线程等一等;
④如果FutureTask的状态为初始态NEW,则将当前线程加入到FutureTask的阻塞线程中去;
⑤如果get方法没有设置超时时间,则阻塞当前调用get线程;如果设置了超时时间,则判断是否达到超时时间,如果到达,则移除FutureTask的所有阻塞列队中的线程,并返回此时FutureTask的状态,如果未到达时间,则在剩下的时间内继续阻塞当前线程。
该方法有个无限循环直到状态值大于COMPLETING才返回一个状态值,我们在线程未执行完成的时候调用了get()方法,可以看到首先会创建一个WaitNode对象,然后通过Unsafe类来更新成员变量waiter的值为 q,然后再次循环最后会进入LockSupport.park(this) 分支,该函数主要是获取许可阻塞当前的线程,直到程序执行结束之后,调用LockSupport.unpark(this)来释放阻塞。所以如果我们在主线程中直接调用get()方法来获取结果的话则很有可能导致ANR,直到程序结束之后才会释放阻塞的,正确的用法就是在done()方法里面调用get()来获取执行的结果的。

我们平时在使用AsyncTask的时候有一个cancel()方法来取消当前执行的任务,我们之前也说了AsyncTask的本质其实也是使用了FutureTask来实现的。其实它的cancel()方法也是调用FutureTask的取消方法的,下面看看取消的原理:
//如果返回值为true的话表示取消成功,否则为取消失败了
public boolean cancel(boolean mayInterruptIfRunning) {

//首先判断当前的状态是否是NEW,然后再通过Unsafe类去更新内存中state字段的值为cancel。
if (!(state == NEW &&
UNSAFE.compareAndSwapInt(this, stateOffset, NEW, mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
return false;
try {

//如果以上的状态值设置成功的话,则判断是否设置中断运行
if (mayInterruptIfRunning) {

try {

Thread t = runner;
//直接通过调用Thread的中断方法来强制中断当前运行的线程
if (t != null)
t.interrupt();
} finally { // final state
//最后修改当前状态state的值为 INTERRUPTED 为中断
UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED);
}
}
} finally {

//最后解锁所有被阻塞的线程
finishCompletion();
}
return true;
}
第一行代码,是一个校验,如果state值为NEW, 根据mayInterruptIfRunning是否为true把state值由NEW变为INTERRUPTING或者CANCELLED,如果都成功了,则继续执行下一步,否则,终止,返回失败。比如已经执行完耗时操作,state值已经变成了COMPLETING,此时就不能取消了,直接返回false,表示失败;如果还没开始执行,或者执行了,但还没执行完,还在耗时操作之中,则根据 mayInterruptIfRunning 值,state 值由NEW变为INTERRUPTING或CANCELLED,此时,即使执行了run()方法,set(v)时也会有if (U.compareAndSwapInt(this, STATE, NEW, COMPLETING))这个校验,此时state为INTERRUPTING或者CANCELLED,就不会继续赋值了。 继续往下看, 如果mayInterruptIfRunning为true,则会获取到耗时操作的线程,如果该线程已经执行,说明线程存在,不为空,则把它强制终止,然后会把state值由INTERRUPTING变为INTERRUPTED,表示已经终止,INTERRUPTING的意思是终止进行中。然后会执行 finishCompletion(); 方法。
我们在取消任务的时候可以设置强制中断线程运行,只要调用cancel(true) 就行了,有时候我们调用cancel(false)并不能立刻停止线程执行完成的,因为这个时候程序在run()方法中已经执行过了状态(state)值判断的话,这个时候就直接执行call()方法了,但是call()方法也没有执行完成,如果这个时候我们去取消的话, 因为我们知道取消的原理就是使用Unsafe类去修改内存中的state的值,但是这个时候设置已经来不急了。

虽然我们调用了cancel(false)方法去取消任务的,但是很多的时候还是不能马上终止任务执行,最后线程还是会继续执行的,但是到了set()方法的时候,这里会有一个状态值的判断的。之前我们已经介绍了线程并发的基石CAS,首先我们使用Unsafe类去比较state状态值是否发生了变化,如果state的值被其他的线程修改了,则不会调用done()方法了。
protected void set(V v) {

if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {


}
}

4.FutureTask的完整源码
把FutureTask的完整代码写出来,整体思路理一下:
public class FutureTask< V> implements RunnableFuture< V> {

private volatile int state;
private static final int NEW = 0;
private static final int COMPLETING = 1;
private static final int NORMAL = 2;
private static final int EXCEPTIONAL = 3;
private static final int CANCELLED = 4;
private static final int INTERRUPTING = 5;
private static final int INTERRUPTED = 6;
private Callable< V> callable;
private Object outcome;
private volatile Thread runner;
private volatile WaitNode waiters;

public FutureTask(Callable< V> callable) {

if (callable == null)
throw new NullPointerException();
this.callable = callable;
this.state = NEW;
}

public FutureTask(Runnable runnable, V result) {

this.callable = Executors.callable(runnable, result);
this.state = NEW;
}

public void run() {

if (state != NEW ||
!UNSAFE.compareAndSwapObject(this, runnerOffset,null, Thread.currentThread()))
return;
try {

Callable< V> c = callable;
if (c != null && state == NEW) {

V result;
boolean ran;
try {

result = c.call();
ran = true;
} catch (Throwable ex) {

result = null;
ran = false;
setException(ex);
}
if (ran)
set(result);
}
} finally {

runner = null;
int s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
}
}

public boolean isCancelled() {

return state >= CANCELLED;
}

public boolean isDone() {

return state != NEW;
}

public boolean cancel(boolean mayInterruptIfRunning) {

if (!(state == NEW &&
UNSAFE.compareAndSwapInt(this, stateOffset, NEW, mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
return false;
try {

if (mayInterruptIfRunning) {

try {

Thread t = runner;
if (t != null)
t.interrupt();
} finally { // final state
UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED);
}
}
} finally {

finishCompletion();
}
return true;
}

public V get() throws InterruptedException, ExecutionException {

int s = state;
if (s <= COMPLETING)
s = awaitDone(false, 0L);
return report(s);
}

public V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {

if (unit == null)
throw new NullPointerException();
int s = state;
if (s <= COMPLETING &&
(s = awaitDone(true, unit.toNanos(timeout))) <= COMPLETING)
throw new TimeoutException();
return report(s);
}

//Returns result or throws exception for completed task.
//@param s: completed state value
@SuppressWarnings(“unchecked”)
private V report(int s) throws ExecutionException {

Object x = outcome;
if (s == NORMAL)
return (V)x;
if (s >= CANCELLED)
throw new CancellationException();
throw new ExecutionException((Throwable)x);
}

protected void done() { }

protected void set(V v) {

if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {

outcome = v;
UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
finishCompletion();
}
}

protected void setException(Throwable t) {

if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {

outcome = t;
UNSAFE.putOrderedInt(this, stateOffset, EXCEPTIONAL); // final state
finishCompletion();
}
}

private void finishCompletion() {

for (WaitNode q; (q = waiters) != null;) {

if (UNSAFE.compareAndSwapObject(this, waitersOffset, q, null)) {

for (;😉 {

Thread t = q.thread;
if (t != null) {

q.thread = null;
LockSupport.unpark(t);
}
WaitNode next = q.next;
if (next == null)
break;
q.next = null; // unlink to help gc
q = next;
}
break;
}
}
done();
callable = null; // to reduce footprint
}

private int awaitDone(boolean timed, long nanos)
throws InterruptedException {

final long deadline = timed ? System.nanoTime() + nanos : 0L;
WaitNode q = null;
boolean queued = false;
for ( ; ; ) {

if (Thread.interrupted()) {

removeWaiter(q);
throw new InterruptedException();
}
int s = state;
if (s > COMPLETING) {

if (q != null)
q.thread = null;
return s;
}
else if (s = = COMPLETING)
Thread.yield();
else if (q == null)
q = new WaitNode();
else if (!queued)
queued = UNSAFE.compareAndSwapObject(this, waitersOffset, q.next = waiters, q);
else if (timed) {

nanos = deadline - System.nanoTime();
if (nanos <= 0L) {

removeWaiter(q);
return state;
}
LockSupport.parkNanos(this, nanos);
}
else
LockSupport.park(this);
}
}

protected boolean runAndReset() {

if (state != NEW ||
!UNSAFE.compareAndSwapObject(this, runnerOffset, null, Thread.currentThread()))
return false;
boolean ran = false;
int s = state;
try {

Callable< V> c = callable;
if (c != null && s = = NEW) {

try {

c.call(); // don’t set result
ran = true;
} catch (Throwable ex) {

setException(ex);
}
}
} finally {

runner = null;
s = state;
if (s >= INTERRUPTING)
handlePossibleCancellationInterrupt(s);
}
return ran && s == NEW;
}

private void handlePossibleCancellationInterrupt(int s) {

if (s = = INTERRUPTING)
while (state == INTERRUPTING)
Thread.yield(); // wait out pending interrupt
}

static final class WaitNode {

volatile Thread thread;
volatile WaitNode next;
WaitNode() {

thread = Thread.currentThread();
}
}

private void removeWaiter(WaitNode node) {

if (node != null) {

node.thread = null;
retry:
for ( ; ; ) { // restart on removeWaiter race
for (WaitNode pred = null, q = waiters, s; q != null; q = s) {

s = q.next;
if (q.thread != null)
pred = q;
else if (pred != null) {

pred.next = s;
if (pred.thread == null)
continue retry;
}
else if ( !UNSAFE.compareAndSwapObject(this, waitersOffset, q, s))
continue retry;
}
break;
}
}
}

private static final sun.misc.Unsafe UNSAFE;
private static final long stateOffset;
private static final long runnerOffset;
private static final long waitersOffset;
static {

try {

UNSAFE = sun.misc.Unsafe.getUnsafe();
Class<?> k = FutureTask.class;
stateOffset = UNSAFE.objectFieldOffset
(k.getDeclaredField(“state”));
runnerOffset = UNSAFE.objectFieldOffset
(k.getDeclaredField(“runner”));
waitersOffset = UNSAFE.objectFieldOffset
(k.getDeclaredField(“waiters”));
} catch (Exception e) {

throw new Error(e);
}
}
}

我的理解:
FutureTask实现了RunnableFuture,它有两个构造方法,可以传入Callable或者Runnable(如果传入Runnable,会通过Executors.callable()将Runnable转换成Callable),然后将传入的Callable赋值给FutureTask的成员变量callable,并把state设置为NEW。当把这个futureTask实例传递给Thread或Executor执行execute方法时,会调用FutureTask的run()方法(因为FutureTask实现了Runnable,所以有run方法),此时进入子线程。在run()方法里,如果state是NEW,就会调用Callable的call()方法执行耗时任务,并获取到执行结果result,通过FutureTask的set(result)方法将结果赋值给成员变量outcome,并将state置为NORMAL,同时执行finishCompletion,将阻塞的线程解锁,并执行done()方法(done方法是需要我们重写的,在这里可以通过get()方法得到outcome的值,也就是子线程的执行结果或者异常)。如果在run方法里调用call时报异常,会通过setException方法将异常赋值给outcome,同样也会调用finishCompletion解除阻塞的线程并执行done方法(所以子线程正常结束或者有异常都会执行done方法)。
简单一点:Thread.execute(futureTask)时,会调用FutureTask的run方法,在run方法里调用了Callable的call方法,我们可以把耗时任务写在call方法里,call方法返回任务结果set,然后调用done,在done里我们就可以get得到结果。
使用FutureTask一共分为4步:①定义类实现Callable;②定义FutureTask,把Callable当做参数传入;③定义Thread,传入FutureTask;④Thread.start。我们需要做的就是在Callable的call()方法里写耗时操作(子线程),然后在FutureTask的done()方法里得到子线程的执行结果(注意done也在子线程)

今天的分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

发表回复