Callable接口获得线程
继承Thread类和Runnable接口方式
有两种创建线程的方法-一种是通过创建Thread类,另一种是通过使用Runnable创建线程。
public class MyThread implements Runnable { // 实现 Runnable 接口方式
@Override
public void run() {
// do something
}
}
public class myThread2 extends Thread { // 继承 Thread 类方式
@Override
public void run() {
// do something
}
}
实现Callable接口方式
Runnable缺少的一项功能是,当线程终止时(即run()方法完成时),无法使线程返回结果。为了支持此功能,Java中提供了Callable接口。
public static void main(String[] args) throws ExecutionException, InterruptedException {
MyThread1 thread = new MyThread1();
FutureTask<Integer> task = new FutureTask<>(thread);
// 启用多个线程 任务也只会被执行一次
new Thread(task, "A").start();
new Thread(task, "B").start();
System.out.println(" main线程执行完成");
System.out.println(task.get()); // 一般在方法最后获取这个返回值,否则线程会被阻塞 一直等待任务完成
}
// Runnable 接口与 Callable 接口不同点
// 1、实现方法不同 Runnable 是重写 run() 方法, Callable 是重写call() 方法
// 2、Runnable run() 方法不抛出异常, Callable call() 方法 抛出异常
// 3、Runnable run() 方法没有返回值,Callable call() 方法有返回值
public static class MyThread1 implements Callable<Integer> {
@Override
public Integer call() throws Exception {
System.out.println(String.format("开始时间%s", LocalDateTime.now()));
System.out.println(Thread.currentThread().getName() + "开始执行");
// return 2 << 8;
return (int) (Math.random() * 100);
}
}
FutureTask类源码简介
volatile修饰的state字段
// volatile修饰的state字段
/*
* 可能的状态变更:
* NEW -> COMPLETING -> NORMAL 正常执行没有发生异常,也没有被取消
* NEW -> COMPLETING -> EXCEPTIONAL 执行过程中发生异常
* NEW -> CANCELLED 任务被取消
* NEW -> INTERRUPTING -> INTERRUPTED 任务被中断
*/
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; // 已中断
FutureTask中的其它变量
/** The underlying callable; nulled out after running */
private Callable<V> callable; // 将要执行的任务
/** The result to return or exception to throw from get() */
private Object outcome; // 储存结果 // non-volatile, protected by state reads/writes
/** The thread running the callable; CASed during run() */
private volatile Thread runner; // 执行任务的线程
/** Treiber stack of waiting threads */
private volatile WaitNode waiters; // get方法阻塞的线程队列
static final class WaitNode {
volatile Thread thread;
volatile WaitNode next;
WaitNode() { thread = Thread.currentThread(); } // 链式的线程 Thread
}
FutureTask中的CAS工具初始化
// Unsafe mechanics
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.run()方法相关
// run() 方法执行任务过程
public void run() {
// 状态不是 NEW新建状态 或者 runner的旧值不是null 任务将不会被执行
// 多个线程竞争执行任务时 状态可能还是NEW 但是利用CAS方式获取期望的旧值不是null 任务已经被其它线程执行 将会直接返回。
// public final native boolean compareAndSwapObject(Object var1, long var2, Object var4, Object var5);
if (state != NEW ||
!UNSAFE.compareAndSwapObject(this, runnerOffset,
null, Thread.currentThread()))
return;
try { // 开始执行任务
Callable<V> c = callable;
if (c != null && state == NEW) { // 状态是NEW 且callable不为null时执行
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 must be non-null until state is settled to
// prevent concurrent calls to run()
runner = null; // 设置 runner为null 防止并发调用run() 方法
// state must be re-read after nulling runner to prevent
// leaked interrupts
int s = state; // 重读state 防止中断泄漏
if (s >= INTERRUPTING) // 任务处于中断中的状态,则进行中断操作
handlePossibleCancellationInterrupt(s);
}
}
protected void set(V v) { // 正常运行时设置返回值
// 将状态设置为完成中间状态 COMPLETING = 1; // 完成的中间状态
if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
outcome = v; // 返回值
// 将状态更新为 NORMAL = 2; // 已正常完成的状态
UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
finishCompletion();
}
}
protected void setException(Throwable t) { // 设置异常
// 将状态设置为完成中间状态 COMPLETING = 1; // 完成的中间状态
if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
outcome = t; // 设置返回的结果值为异常信息
// 将状态更新为 EXCEPTIONAL = 3; // 异常终止状态
UNSAFE.putOrderedInt(this, stateOffset, EXCEPTIONAL); // final state
finishCompletion();
}
}
// 确保cancel(true)方法调用时,产生的中断发生仅发生在run或runAndReset方法过程中。
private void handlePossibleCancellationInterrupt(int s) {
// It is possible for our interrupter to stall before getting a
// chance to interrupt us. Let's spin-wait patiently.
if (s == INTERRUPTING)
while (state == INTERRUPTING)
// 让出cpu时间片,等待cancel(true)执行完成,此时INTERRUPTING必然能更成INTERRUPTED
Thread.yield(); // wait out pending interrupt
// assert state == INTERRUPTED;
// We want to clear any interrupt we may have received from
// cancel(true). However, it is permissible to use interrupts
// as an independent mechanism for a task to communicate with
// its caller, and there is no way to clear only the
// cancellation interrupt.
//
// Thread.interrupted();
}
// 由中间状态变更为最终状态时,都需要进行的操作
// 移除并唤醒所有等待的线程,调用done(),并清空Callable
private void finishCompletion() {
// assert state > COMPLETING; 断言状态大于完成的中间状态
for (WaitNode q; (q = waiters) != null;) {
// 尝试将waiters 全部设置为null
if (UNSAFE.compareAndSwapObject(this, waitersOffset, q, null)) {
for (;;) { // 将waiters下对应的链式线程 Thread逐个唤醒
Thread t = q.thread;
if (t != null) {
q.thread = null;
LockSupport.unpark(t); // 唤醒操作,LockSupport.unpark() 阻塞
}
WaitNode next = q.next;
if (next == null)
break;
q.next = null; // unlink to help gc 断开链接
q = next;
}
break;
}
}
done();
callable = null; // to reduce footprint
}
protected void done() { } // 子类可重写该方法,实现回调
FutureTask.get() 方法相关
/**
* 获取返回值 不设置等待时间
*/
public V get() throws InterruptedException, ExecutionException {
int s = state;
if (s <= COMPLETING) // 如果状态是 NEW 或者 COMPLETING 新建或者执行中的状态 需要等待task执行完成
s = awaitDone(false, 0L);
return report(s); // 返回最后的结果值
}
/**
* 获取返回值,包含超时时间
*/
public V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException {
if (unit == null) // TimeUnit 必须设置
throw new NullPointerException();
int s = state;
// 如果是新建或者中间状态,等待task执行完成,如果超过了指定时间task依旧是未完成,会抛出超时异常
if (s <= COMPLETING &&
(s = awaitDone(true, unit.toNanos(timeout))) <= COMPLETING)
throw new TimeoutException();
return report(s);// 返回最后的结果值
}
/**
* boolean timed 是否需要等待
* long nanos 等待时间 单位是纳秒
* 等待完成,可能是是中断、异常、正常完成
*/
private int awaitDone(boolean timed, long nanos)
throws InterruptedException {
// 如果设置的超时时间,计算出一个过期时间
final long deadline = timed ? System.nanoTime() + nanos : 0L;
WaitNode q = null;
boolean queued = false;
for (;;) { // 无限循环
// 1、如果线程已中断,则直接将当前节点q从waiters中移出
if (Thread.interrupted()) {
removeWaiter(q);
throw new InterruptedException();
}
// 2、如果state已经是最终状态了,则直接返回state
int s = state;
if (s > COMPLETING) {
if (q != null)
q.thread = null;
return s;
}
else if (s == COMPLETING) // 3、cannot time out yet 如果state是中间状态(COMPLETING),意味很快将变更成最终状态,让出cpu时间片即可 此时将不受超时时间的限制
Thread.yield();
else if (q == null) // 4、如果发现尚未有节点,则创建节点
q = new WaitNode();
else if (!queued) // 5、如果当前节点尚未入队,则将当前节点放到waiters中的首节点,并替换旧的waiters
queued = UNSAFE.compareAndSwapObject(this, waitersOffset,
q.next = waiters, q);
else if (timed) { // 6、线程被阻塞指定时间后再唤醒
nanos = deadline - System.nanoTime();
if (nanos <= 0L) { // 如果已经超时直接返回
removeWaiter(q); // 从waiters中移出节点q
return state;
}
LockSupport.parkNanos(this, nanos);
}
else // 7、线程一直被阻塞直到被其他线程唤醒
LockSupport.park(this);
}
}
// 删除节点
private void removeWaiter(WaitNode node) {
if (node != null) {
node.thread = null; // 将需要去除的节点,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) { // q.thread==null,表示该节点是需要在队列中去除的节点,直接将pred.next=s,重组队列
pred.next = s;
if (pred.thread == null) // check for race 如果这个pred节点恰好是需要去除的节点,则进行循环,重组队列
continue retry;
}
else if (!UNSAFE.compareAndSwapObject(this, waitersOffset,
q, s))
continue retry;
}
break;
}
}
}
// 获取返回值
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); // 抛出run()方法设置的异常
}
FutureTask.cancel() 方法相关
// 取消任务
// boolean mayInterruptIfRunning 是否可进行中断操作 INTERRUPTING 或者 CANCELLED 直接返回false
public boolean cancel(boolean mayInterruptIfRunning) {
// 状态不是新建 NEW 且无法将状态更新为
if (!(state == NEW &&
UNSAFE.compareAndSwapInt(this, stateOffset, NEW,
mayInterruptIfRunning ? INTERRUPTING : CANCELLED)))
return false;
try { // in case call to interrupt throws exception
if (mayInterruptIfRunning) { // 允许进行取消/中断操作
try {
Thread t = runner;
if (t != null)
t.interrupt(); // 取消操作 需要注意并不是实时取消
} finally { // final state
UNSAFE.putOrderedInt(this, stateOffset, INTERRUPTED); // 中断成功设置为最终状态
}
}
} finally {
finishCompletion();
}
return true;
}
CAS相关原理需要再深入理解一下,先挖个坑