在JDK中,我们可以通过以下方式新开线程并执行:
1.继承Thread类,并重写run()方法
public class MyThread extends Thread {
@Override
public void run() {
//开发业务需求
}
}
2.实例化Thread的对象,并传递Runnable实现类的对象
Runnable runnable = new Runnable() {
public void run() {
// 开发业务需求
}
};
Thread thread = new Thread(runnable);
thread.start();
3.使用JDK提供的线程池执行线程
// 用Executors类提供的相关方法生成
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.submit(new Runnable() {
public void run() {
// 开发业务需求
}
});
在开发程序过程中,我们可能在线程运行的同时需要获取到线程的执行结果,一般有以下3种方式实现:
1.继承Thread类并重写run()方法 或者 传递Runnable实现类的对象,这种需要定义接口来实现,而这对代码的耦合度比较高,需要在接入业务外的代码。
2. 使用JDK提供的线程池来执行线程,通过submit()返回Future类,Future类可以调用get()获取到结果。
3.使用JDK提供的FutureTask类来实现。
本文主要讲解第三种方式实现,一般的实现代码如下:
FutureTask<String> task = new FutureTask<String>(new Callable<String>() {
public String call() {
try {
Thread.sleep(5000);
// ... do something
} catch (Exception e) {
}
return "Hello world";
}
});
new Thread(task).start();
try {
System.out.println(task.get());
} catch (Exception e) {
}
下面开始讲解 JDK中的 Callable、Future、FutureTask三个类
public interface Callable<V> {
V call() throws Exception;
}
Callable接口定义了call()
Callable接口可以看作是Runnable接口的升级版,定义了获取运行结果的方法。
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接口定义了一组异步计算的方法:
cancel():尝试取消执行当前任务,当任务未执行时直接取消,执行正在执行时,mayInterruptIfRunning参数决定是否中断
get():需要检测当前任务是否完成,已完成则返回结果,未完成需要wait直到任务完成。
接下来重点讲解下FutureTask类
public class FutureTask<V> implements RunnableFuture<V> {
}
FutureTask类实现了RunnableFuture接口
public interface RunnableFuture<V> extends Runnable, Future<V> {
}
RunnableFuture接口继承Runnable接口,Future接口
new Thread(task).start();
当线程启动的时候,调用FutureTask的run()方法
1.run()
public void run() {
// 任务不处于初始化状态 或者 当前任务的runner不为null,表明当前任务已开始
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 {
// 执行开发者重写的call方法
result = c.call();
ran = true;
} catch (Throwable ex) {
// 当call方法抛出异常
result = null;
ran = false;
// 1.1
setException(ex);
}
// call方法顺利执行完成
if (ran)
// 1.2
set(result);
}
} finally {
// runnable记录第一个执行run()的thread对象 通过CAS防止run()被同时调用
// 当state改变时 runnable=null
runner = null;
int s = state;
if (s >= INTERRUPTING)
// 1.3
handlePossibleCancellationInterrupt(s);
}
}
1.1 setException(Throwable t)
// run()遇到Exception时调用
protected void setException(Throwable t) {
// 将当前任务的状态设置为COMPLETING状态
if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
outcome = t;
// 将当前任务设置为最终状态 EXCEPTIONAL
UNSAFE.putOrderedInt(this, stateOffset, EXCEPTIONAL); // final state
// 1.1.1
finishCompletion();
}
}
1.2 set(V v)
// run()成功执行后调用
protected void set(V v) {
// 设置当前状态为COMPLETING状态
if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
// 记录结果
outcome = v;
// 设置当前状态为最终状态NORMAL
UNSAFE.putOrderedInt(this, stateOffset, NORMAL); // final state
// 1.1.1
finishCompletion();
}
}
1.1.1 finishCompletion()
// 任务执行完 或者 取消后调用
private void finishCompletion() {
// assert state > COMPLETING;
// WaitNode类
// static final class WaitNode {
// volatile Thread thread;
// volatile WaitNode next;
// WaitNode() { thread = Thread.currentThread(); }
// }
// WaitNode对象 用单链表来记录哪个线程调用get()
// 通过CAS自旋锁将当前waiters对象置为null
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;
}
2.1 get()
public V get() throws InterruptedException, ExecutionException {
int s = state;
// 如果当前任务状态处于 NEW || COMPLETING 则将进入等待队列
if (s <= COMPLETING)
// 2.2
s = awaitDone(false, 0L);
// 2.3
return report(s);
}
2.2 awaitDone(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 (;;) {
// 如果当前线程被中断 将当前的waitNode从等待栈移除
if (Thread.interrupted()) {
// 2.2.1
removeWaiter(q);
throw new InterruptedException();
}
// 如果此时当前任务状态为已完成||取消 则直接返回得到结果
int s = state;
if (s > COMPLETING) {
if (q != null)
q.thread = null;
return s;
}
// 如果此时任务状态为完成中 则将线程的时间片让掉 等待下一轮分配CPU分配时间片
else if (s == COMPLETING) // cannot time out yet
Thread.yield();
else if (q == null)
q = new WaitNode();
else if (!queued)
// 将当前的waitNode加入等待栈 插入作为头部
queued = UNSAFE.compareAndSwapObject(this, waitersOffset,
q.next = waiters, q);
else if (timed) {
nanos = deadline - System.nanoTime();
// 如果设置为定时模式并且当前时间超过设置的时间 立即返回
if (nanos <= 0L) {
// 2.2.1
removeWaiter(q);
return state;
}
// 使用UnSafe类挂起线程nanos毫秒
LockSupport.parkNanos(this, nanos);
}
else
// 使用UnSafe类挂起线程
LockSupport.park(this);
}
}
2.2.1 removeWaiter(WaitNode node)
//删除指定节点 Treiber算法无锁删除节点
private void removeWaiter(WaitNode node) {
if (node != null) {
//将WaitNode的线程置为null,根据thread是否为null判断是否要把node移出
node.thread = null;
retry:
for (;;) {
for (WaitNode pred = null, q = waiters, s; q != null; q = s) {
s = q.next;
// pred记录当前node的上个节点
if (q.thread != null)
pred = q;
// 执行到这里说明 q.thread为null 节点node是需要删除的节点
else if (pred != null) {
// 将上个节点指向下个节点
pred.next = s;
// pred.thread为null 有其他线程也在执行removeWaiter方法 重新从外层循环执行
if (pred.thread == null) // check for race
continue retry;
}
// 执行到这里说明 WaitNode在栈顶 通过CAS将node的下个节点赋给waiters
else if (!UNSAFE.compareAndSwapObject(this, waitersOffset, q, s))
continue retry;
}
break;
}
}
}
2.3 report(int s)
private V report(int s) throws ExecutionException {
Object x = outcome;
// 当前任务状态为成功正常 将结果返回
if (s == NORMAL)
return (V)x;
// 当前任务被取消 抛出CancellationException
if (s >= CANCELLED)
throw new CancellationException();
// 执行到这里 任务处于NEW COMPLETING EXCEPTIONAL则抛出ExecutionException
throw new ExecutionException((Throwable)x);
}
总结:
Callable接口定义了可获取方法结果,可以看作是Runnable接口的升级版。
Future接口定义了针对任务操作的一系列接口。
FutureTask类是Future接口、Runnable接口的实现类,旨在提供针对任务的操作的实现。当线程启动时,将任务的runnable线程设置为执行线程,防止被其他线程启动(FutureTask类实例对象只能被一个线程执行),执行期间,调用get()将进入等待队列并将所在线程挂起,执行完毕,将等待队列的线程恢复,返回结果。
在FutureTask源码中我们看到很多Unsafe调用的方法,对Unsafe不了解可戳>>Unsafe类