FutureTask源码分析

这个是核心代码,首先我们需要知道FutureTask中有一个volatile state全局变量,通过这个值来界定任务是否已经执行完毕

run方法

先判断state状态,如果不是NEW说明执行完毕,直接return掉。 后面使用CAS操作,判断这个任务是否已经执行,这里FutureTask有个全局的volatile runner字段,这里通过cas将当前线程指定给runner。 下面主要是这样操作:

1、判断状态是不是NEW,不是的话说明已经结束或者取消。调用CAS方法,判断runner是否null

2、执行Callable,返回call方法的结果(Object),异常设置异常,最后finally处理异常并调用Tread.yield让出时间片

 

查看set方法具体实现:

查看finishCompletion方法:

FutureTask中有一个WaiteNode单链表,当执行futureTask.get()方法时,多个线程会将等待的线程的next指向下一个想要get获取结果的线程。

finishCompletion主要就是使用Unsafe.unpark()进行唤醒操作

1、Unsafe的CAS,提供了对runner一种原子操作,意味着不会被打断,runner被volatile修饰,只能保证当前多个子线程再执行futuretask的时候,读取的runner是同一个值,但不能保证没有脏数据(比如,线程A准备对runner进行读写操作,读到null,这是CPU切换B,B读到null,然后切换A,A赋值为Tread-c,此时B读到的null为脏数据)用Unsafe的操作,多个线程访问run方法的时候,会在这里同步

FutureTask.get() 源码

get() 方法会进行自旋操作等待,直到FutureTask中的state状态大于NORMAL(表示自行完成),然后才会通过FutureTask的outcome获取返回值。

cancle方法

 

1、先判断state,保证state=NEW才能继续cancel的后续操作。state=NEW且为mayInterruptIfRunning=true,说明要中断任务的执行,此时NEW->interrupting,然后读取当前执行的任务线程runner,调用interrupt方法,中断线程执行,最后调用finishCompletion方法

2、如果NEW->interrupting,那么cancel只是修改了状态,new-->canceled,然后直接调用finishCompletion。所以cancel(true)方法,只是调用了t.interrupt,如果此时线程的状态是sleep、wait、join等方法进入阻塞的话,那么就会抛出InterruptedException,如果线程正常运行,需要判断Tread.interrupted方法进行判断,才能结束,否则不能结束cancel方法,所有cancel不能真正的结束子任务执行

但是发现源码,interrupt方法是Tread.interrupt,那么解决的话只能加上Tread.currentTread().isInterrupted()方法判断

get方法

get方法一般是获取任务执行结果,执行任务的线程和获取结果的线程不会是同一个,当我们在主线程或者其他线程中,获取计算任务的结果时,就会调用get方法,如果这时计算任务还没有执行完成,调用get的线程就会阻塞

 

 

1、移除WaitNode等待队列节点,线程中断直接抛出中断异常

2、如果任务正常结束或者异常结束,不阻塞,直接返回,并且创建q节点,直接赋值null返回

3、如果任务还没保存到outcome字段,且任务已结束,让出时间片

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值