關(guān)于上下文請(qǐng)看 線程本質(zhì),下面我們直接進(jìn)入正題。
使用
先看看我們平時(shí)使用的方式,使用線程常見的代碼如下:
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
while (true) {
// 噠噠噠噠
}
}
});
thread.start();
然后我們知道里邊的代碼不會(huì)阻塞當(dāng)前的執(zhí)行流,而是新開一個(gè)異步線程去執(zhí)行 while 循環(huán),但是,為什么呢?
為什么就不會(huì)阻塞 UI 線程?
以及它到底是如何調(diào)度系統(tǒng)資源的?
或者直接一點(diǎn),這貨到底是怎么實(shí)現(xiàn)的?
代碼
帶著上邊的問(wèn)題,我們先來(lái)看一下 java 端的代碼Thread.java,Java 層的線程實(shí)現(xiàn)自然是最簡(jiǎn)單的,搞 Android 或者 java 的對(duì)這個(gè)應(yīng)該也很熟悉。這里我們簡(jiǎn)要介紹一下:
為了方便,我們先把 Runnable 貼一下,因?yàn)?Thread implements Runnable。
// 就是一個(gè)接口定義了一個(gè) run 方法,這里不多說(shuō)
public interface Runnable {
public abstract void run();
}
然后我們?cè)诎?Thread 的幾個(gè)主要屬性及函數(shù)列一下(不關(guān)主線的代碼就都刪掉了):
package java.lang;
public class Thread implements Runnable {
// 先執(zhí)行 native 函數(shù)來(lái)做一些注冊(cè)相關(guān)的東西
private static native void registerNatives();
static {
registerNatives();
}
private Runnable target;
// 優(yōu)先級(jí)
public final static int MIN_PRIORITY = 1;
public final static int NORM_PRIORITY = 5;
public final static int MAX_PRIORITY = 10;
private int priority;
public final void setPriority(int newPriority) {
...
setPriority0(priority = newPriority);
}
public final int getPriority() {
return priority;
}
// 以下幾個(gè)變量會(huì)在 native 層 classloader 時(shí)被調(diào)用,這里不做過(guò)多解釋(這里其實(shí)也是應(yīng)該刪掉的)
private Thread threadQ;
private long eetop;
private boolean single_step;
private boolean stillborn = false;
private long nativeParkEventPointer;
// ThreadGroup 相關(guān)
private ThreadGroup group;
public final ThreadGroup getThreadGroup() {
return group;
}
public static int activeCount() {
return currentThread().getThreadGroup().activeCount();
}
public static int enumerate(Thread tarray[]) {
return currentThread().getThreadGroup().enumerate(tarray);
}
// name 相關(guān)(就是日志中打印出來(lái)的線程名字),當(dāng)線程初始化時(shí),會(huì)根據(jù) threadInitNumber 來(lái)自動(dòng)生成線程名字
private char name[];
private static int threadInitNumber;
private static synchronized int nextThreadNum() {
return threadInitNumber++;
}
public final void setName(String name) {
...
this.name = name.toCharArray();
}
public final String getName() {
return String.valueOf(name);
}
// tid 相關(guān)(線程 id),通過(guò) threadSeqNumber 的累加來(lái)賦值 tid(與 native 層的線程 id 沒(méi)有一毛錢關(guān)系)
private long tid;
private static long threadSeqNumber;
private static synchronized long nextThreadID() {
return ++threadSeqNumber;
}
public long getId() {
return tid;
}
// ThreadLocal,主要用來(lái)存儲(chǔ)線程獨(dú)有的變量,如果想了解的話可以參考 [ThreadLocal 框架](http://www.itdecent.cn/p/e34ec28bf7a4)
ThreadLocal.ThreadLocalMap threadLocals = null;
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
//線程狀態(tài)
private int threadStatus = 0;
public enum State {
NEW,
RUNNABLE,
BLOCKED,
WAITING,
TIMED_WAITING,
TERMINATED;
}
public State getState() {
return sun.misc.VM.toThreadState(threadStatus);
}
// 線程休眠
public static void sleep(long millis, int nanos) throws InterruptedException {
。。。
sleep(millis);
}
// 初始化
private void init(ThreadGroup g, Runnable target, String name,
long stackSize) {
Thread parent = currentThread();
...
this.group = g;
this.priority = parent.getPriority();
this.name = name.toCharArray();
this.target = target;
setPriority(priority);
....
tid = nextThreadID();
}
// 構(gòu)造函數(shù),有多個(gè),為了方便展示框架,這里只貼了一個(gè)
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
// 開始真正執(zhí)行此線程
public synchronized void start() {
...
start0();
...
}
// 沒(méi)什么好說(shuō)的,直接執(zhí)行了 Runnable 的 run 函數(shù)
public void run() {
if (target != null) {
target.run();
}
}
// 判斷當(dāng)前線程是否中斷
public void interrupt() {
...
interrupt0();
}
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
public boolean isInterrupted() {
return isInterrupted(false);
}
// 阻塞調(diào)用此函數(shù)的線程,直到 join 歸屬的 Thread 實(shí)例執(zhí)行完。核心就是執(zhí)行了 wait,而 wait 這個(gè)函數(shù)其實(shí)也是 native 實(shí)現(xiàn)
public final synchronized void join(long millis) throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
...
if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
// native 相關(guān)函數(shù)
public static native boolean holdsLock(Object obj);
private native static StackTraceElement[][] dumpThreads(Thread[] threads);
private native static Thread[] getThreads();
public static native Thread currentThread();
public static native void yield();
public static native void sleep(long millis) throws InterruptedException;
private native boolean isInterrupted(boolean ClearInterrupted);
public final native boolean isAlive();
private native void start0();
private native void setPriority0(int newPriority);
private native void stop0(Object o);
private native void suspend0();
private native void resume0();
private native void interrupt0();
}
總結(jié)
不多說(shuō),其實(shí) Java 層的線程就是一層皮,沒(méi)有什么實(shí)質(zhì)性的邏輯,沒(méi)有任何申請(qǐng)內(nèi)存等相關(guān)的邏輯,就連 tid 都是根據(jù) ++threadInitNumber 疊加出來(lái)的,與 native 層的完全沒(méi)有關(guān)系。
我們發(fā)現(xiàn)我們上邊的疑惑仍然沒(méi)有得到解答,那我們接下來(lái)就看一下 native 層的實(shí)現(xiàn)。