目錄
1.Thread
1.1start方法源碼解析
// 創建一個新的線程
public synchronized void start() {
// 如果沒有初始化,拋異常
if (threadStatus != 0)
throw new IllegalThreadStateException();
group.add(this);
// started 是個標識符,我們在做一些事情的時候,經常這麼寫
// 動作發生之前標識符是 false,發生完成之後變成 true
boolean started = false;
try {
// 這裏會創建一個新的線程,線程狀態改變爲可執行狀態等待分配時間片
start0();
// 這裏執行的還是主線程
started = true;
} finally {
try {
// 如果失敗,把線程從線程組中刪除
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {}
}
}
// 開啓新線程使用的是 native 方法
private native void start0();
先將該線程加入到線程組裏面,然後纔會使用start0方法將線程狀態改變爲可執行狀態等待cpu分配時間片
1.2初始化源碼分析
// 無參構造器,線程名字自動生成
public Thread() {
init(null, null, "Thread-" + nextThreadNum(), 0);
}
// g 代表線程組,線程組可以對組內的線程進行批量的操作,比如批量的打斷 interrupt
// target 是我們要運行的對象
// name 我們可以自己傳,如果不傳默認是 "Thread-" + nextThreadNum(),
// stackSize 可以設置堆棧的大小
private void init(ThreadGroup g, Runnable target, String name,
long stackSize, AccessControlContext acc) {
if (name == null) {
throw new NullPointerException("name cannot be null");
}
this.name = name.toCharArray();
// 當前線程作爲父線程
Thread parent = currentThread();// 初始化的線程會繼承當前線程
this.group = g;// 繼承父線程的線程組
this.daemon = parent.isDaemon();// 繼承父線程的守護屬性
this.priority = parent.getPriority();// 繼承父線程的優先級
// 繼承父線程的上下文類加載器
// @啓動類加載器,@擴展類加載器,@應用程序類加載器,@自定義類加載器
if (security == null || isCCLOverridden(parent.getClass()))
this.contextClassLoader = parent.getContextClassLoader();
else
this.contextClassLoader = parent.contextClassLoader;
// 繼承父線程訪問控制上下文權限
this.inheritedAccessControlContext =
acc != null ? acc : AccessController.getContext();
this.target = target;// 設置Runnable接口
setPriority(priority);// 設置優先級
// 繼承父線程的inheritableThreadLocals值
if (parent.inheritableThreadLocals != null)
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
// 設置棧大小
this.stackSize = stackSize;
// 設置線程id
tid = nextThreadID();
}
初始化線程,先將當前線程作爲父線程,然後繼承父線程的屬性(線程組,守護屬性,優先級,類加載器,訪問權限,ThreadLocal值),然後設置Runnable接口,設置優先級,設置棧大小,設置線程id
2.Future
2.1基本架構
- 定義了異步計算框架,但是get獲取結果是阻塞的;
ps:異步只針對call/run方法的計算任務來說的,獲取結果依然是阻塞的
// 如果任務已經成功了,或已經取消了,是無法再取消的,會直接返回取消成功(true)
// 如果任務還沒有開始進行時,發起取消,是可以取消成功的。
// 如果取消時,任務已經在運行了,mayInterruptIfRunning 爲 true 的話,就可以打斷運行中的線程
// mayInterruptIfRunning 爲 false,表示不能打斷直接返回
boolean cancel(boolean mayInterruptIfRunning);// 取消任務
// 返回線程是否已經被取消了,true 表示已經被取消了
// 如果線程已經運行結束了,isCancelled 和 isDone 返回的都是 true
boolean isCancelled();// 是否已經取消
boolean isDone();// 是否已經運行結束了
// 等待結果返回
// 如果任務被取消了,拋 CancellationException 異常
// 如果等待過程中被打斷了,拋 InterruptedException 異常
V get() throws InterruptedException, ExecutionException;
// 等待,但是帶有超時時間的,如果超時時間外仍然沒有響應,拋 TimeoutException 異常
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
該接口定義了任務取消,等待任務完成,判斷是否取消和是否完成方法
3.FutureTask
3.1整體架構
- 實現了RunnableFuture接口適配器(Runnable和Future接口),並且組合了Callable接口
// 任務狀態
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;//任務被打斷成功
// 組合了 Callable
private Callable<V> callable;
// 異步線程返回的結果
private Object outcome;
// 當前任務所運行的線程
private volatile Thread runner;
// 記錄調用 get 方法時被等待的線程
private volatile WaitNode waiters;
- FutureTask類整合了Runnable、Callable、Future三者的功能
3.2初始化源碼解析
// 使用 Callable 進行初始化
public FutureTask(Callable<V> callable) {
if (callable == null)
throw new NullPointerException();
this.callable = callable;
// 任務狀態初始化
this.state = NEW;
}
// 使用 Runnable 初始化,result一般爲null 。
public FutureTask(Runnable runnable, V result) {
// 把 runnable 直接適配成了 callable。
this.callable = Executors.callable(runnable, result);
//初始化狀態
this.state = NEW;
}
// 轉化 Runnable 成 Callable 的適配器類
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方法,也可以執行Runnable方法
爲了統一簡化類的複雜性,將Runnable通過適配器模式變爲Callable
3.3get源碼解析
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);
}