前言
線程是調(diào)度的基本單位,它被包含在進(jìn)程之中,是進(jìn)程中的實(shí)際運(yùn)作單位。
Java中線程的狀態(tài)有以下幾種:
- 初始化(New)。只是創(chuàng)建了一個Thread對象,進(jìn)行資源分配。還沒有實(shí)際啟動線程。
- 可運(yùn)行(Runnable)。對象創(chuàng)建完畢后調(diào)用start()方法,該線程被添加到線程調(diào)度器中,等待被cpu分配時間片。
- 運(yùn)行中(Running)。創(chuàng)建的線程正在執(zhí)行run方法。
- 阻塞(Blocked)。當(dāng)前線程讓出cpu資源,等待再次進(jìn)入可運(yùn)行狀態(tài)。調(diào)用sleep()、join()、wait()都會進(jìn)入阻塞狀態(tài)。
- 死亡(Dead)。線程調(diào)用完畢,執(zhí)行exit方法釋放內(nèi)存。
線程的初始化過程
進(jìn)入源代碼中可以發(fā)現(xiàn),所有的線程實(shí)例化方法都會調(diào)用init這個函數(shù)。
總的來說主要進(jìn)行了以下幾個步驟:
- 設(shè)置名字
- 獲取線程組
- 權(quán)限校驗(yàn)
- 判斷是否同步父線程數(shù)據(jù)
- 基本變量賦值
/**
* @param g 線程組
* @param target 一個實(shí)現(xiàn)了run()方法的Runnable對象
* @param name 線程的名字
* @param stackSize 當(dāng)前線程指定的棧大小,如果指定為0表示忽略
* @param acc 封裝了對系統(tǒng)資源的訪問權(quán)限
* @param inheritThreadLocals 是否拿到父線程中的數(shù)據(jù)
*/
private void init(ThreadGroup g, Runnable target, String name,
long stackSize, AccessControlContext acc,
boolean inheritThreadLocals) {
if (name == null) {
throw new NullPointerException("name cannot be null");
}
//設(shè)置名字
this.name = name;
//獲取父類線程。因?yàn)樽泳€程實(shí)際上還沒有啟動。如果是main線程啟動一個子線程,currentThread()獲取的就是main線程。
Thread parent = currentThread();
//獲取安全管理器,用于資源的權(quán)限校驗(yàn)。
SecurityManager security = System.getSecurityManager();
//獲取線程組過程,有兩種途徑:通過SecurityManager或父線程。
if (g == null) {
if (security != null) {
g = security.getThreadGroup();
}
if (g == null) {
g = parent.getThreadGroup();
}
}
//權(quán)限校驗(yàn),確定當(dāng)前運(yùn)行的線程是否具有修改線程組的權(quán)限。
g.checkAccess();
if (security != null) {
if (isCCLOverridden(getClass())) {
security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
}
}
//線程組標(biāo)識添加了一個還未啟動的線程。
g.addUnstarted();
this.group = g;
//標(biāo)識是否為守護(hù)線程,與父線程的標(biāo)識一致。
this.daemon = parent.isDaemon();
//設(shè)置優(yōu)先級,與父線程一致
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();
//Runnable賦值
this.target = target;
//設(shè)置優(yōu)先級,不得超過父線程的最大優(yōu)先級
setPriority(priority);
//將父線程的ThreadLocal數(shù)據(jù)復(fù)制到子線程,以便進(jìn)行父子線程通信。
if (inheritThreadLocals && parent.inheritableThreadLocals != null)
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
//棧大小賦值
this.stackSize = stackSize;
//線程id自增
tid = nextThreadID();
}