線程定義
線程是現(xiàn)代操作系統(tǒng)調(diào)度的最小單元,一個(gè)進(jìn)程可以創(chuàng)建多個(gè)線程來提高系統(tǒng)的吞吐量和執(zhí)行效率。
注:進(jìn)程是操作系統(tǒng)資源分配和調(diào)度的基本單位,它可以創(chuàng)建多個(gè)線程,進(jìn)程可創(chuàng)建的線程數(shù)量跟操作系統(tǒng)相關(guān)。
為什么要使用多線程?
- 更多的處理器核心;
- 更快的響應(yīng)時(shí)間;
- 更好的編程模型:java提供了一套完整的jmm規(guī)則,屏蔽了底層的一些操作,開發(fā)人員只需要關(guān)注自己的業(yè)務(wù)邏輯即可。
線程的狀態(tài)
- NEW:初始狀態(tài),線程被構(gòu)建,還未調(diào)用start()方法;
- RUNNABLE:運(yùn)行狀態(tài),在java多線程模型中,就緒和運(yùn)行都是運(yùn)行狀態(tài);
- BLOCKED:阻塞狀態(tài);
- WAITING:等待狀態(tài),比如中斷,需要其他的線程來喚醒;
- TIME_WAITING:超時(shí)等待,可以在指定的時(shí)間內(nèi)自行返回;
- TERMINATED:終止?fàn)顟B(tài),線程執(zhí)行完畢。
Thread源碼分析
- 構(gòu)造線程
構(gòu)造函數(shù):
//無參構(gòu)造方法
public Thread() {
init(null, null, "Thread-" + nextThreadNum(), 0);
}
//帶參構(gòu)造方法
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
public Thread(ThreadGroup group, Runnable target) {
init(group, target, "Thread-" + nextThreadNum(), 0);
}
public Thread(String name) {
init(null, null, name, 0);
}
public Thread(ThreadGroup group, String name) {
init(group, null, name, 0);
}
public Thread(Runnable target, String name) {
init(null, target, name, 0);
}
public Thread(ThreadGroup group, Runnable target, String name) {
init(group, target, name, 0);
}
public Thread(ThreadGroup group, Runnable target, String name, long stackSize) {
init(group, target, name, stackSize);
}
所有的構(gòu)造方法都調(diào)用了init這個(gè)方法,接下來我們就來詳細(xì)的看看init方法到底是怎么來初始化線程的。
初始化線程:
private void init(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc) {
//參數(shù)校驗(yàn),線程name不能為null
if (name == null) {
throw new NullPointerException("name cannot be null");
}
this.name = name.toCharArray();
//當(dāng)前線程就是該線程的父線程
Thread parent = currentThread();
//獲取系統(tǒng)的security
SecurityManager security = System.getSecurityManager();
if (g == null) {
//security不為null時(shí),線程所在group為security的group
if (security != null) {
g = security.getThreadGroup();
}
//security為null時(shí),直接使用父線程的group
if (g == null) {
g = parent.getThreadGroup();
}
}
g.checkAccess();
//授權(quán)
if (security != null) {
if (isCCLOverridden(getClass())) { security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
}
}
g.addUnstarted();
this.group = g;
//將守護(hù)線程、優(yōu)先級(jí)等設(shè)置為父線程的對(duì)應(yīng)屬性
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;
setPriority(priority);
if (parent.inheritableThreadLocals != null)
//創(chuàng)建線程共享變量副本
this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
this.stackSize = stackSize;
//分配線程id
tid = nextThreadID();
}
- 啟動(dòng)線程
public synchronized void start() {
//假若當(dāng)前線程初始化還未做好,不能start,0->NEW狀態(tài)
if (threadStatus != 0)
throw new IllegalThreadStateException();
//通知group該線程即將啟動(dòng),group的未啟動(dòng)線程數(shù)量減1
group.add(this);
boolean started = false;
try {
start0();
started = true;
} finally {
try {
//啟動(dòng)不成功,group設(shè)置當(dāng)前線程啟動(dòng)失敗
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
}
}
}
啟動(dòng)線程其實(shí)做了這么幾件事:
- 檢查線程是否初始化;
- 通知group,線程啟動(dòng);
- 調(diào)用native方法start0()啟動(dòng)線程,啟動(dòng)后執(zhí)行run()方法;
- 啟動(dòng)失敗容錯(cuò)處理。
-
線程中斷
中斷可以理解為一個(gè)標(biāo)識(shí)位的屬性,它標(biāo)識(shí)一個(gè)運(yùn)行中的線程是否被其他線程進(jìn)行了中斷操作。
中斷線程:
public void interrupt() {
//中斷其他線程,需要先判斷當(dāng)前線程是否允許修改其他線程
if (this != Thread.currentThread())
checkAccess();
//中斷該線程
synchronized (blockerLock) {
Interruptible b = blocker;
if (b != null) {
interrupt0();//設(shè)置中斷標(biāo)識(shí)位
b.interrupt(this);
return;
}
}
interrupt0();
}
查看當(dāng)前線程是否被中斷:
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
查看線程是否被中斷,已中斷返回false
public boolean isInterrupted() {
return isInterrupted(false);
}
- 線程的暫停、恢復(fù)和停止
注: 這幾個(gè)操作都加有@Deprecated注解,不推薦程序員使用
暫停:
//可能會(huì)造成死鎖
@Deprecated
public final void suspend() {
checkAccess();
suspend0();
}
恢復(fù):
//可能會(huì)造成死鎖
@Deprecated
public final void resume() {
checkAccess();
resume0();
}
停止:
@Deprecated
public final synchronized void stop(Throwable obj) {
if (obj == null)
throw new NullPointerException();
SecurityManager security = System.getSecurityManager();
if (security != null) {
checkAccess();
if ((this != Thread.currentThread()) ||
(!(obj instanceof ThreadDeath))) {
security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION);
}
}
//線程還未初始化好,暫停該線程
if (threadStatus != 0) {
resume();
}
//jvm處理線程相關(guān)內(nèi)容
stop0(obj);
}
- 線程優(yōu)先級(jí)設(shè)置
public final void setPriority(int newPriority) {
ThreadGroup g;
checkAccess();
if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
throw new IllegalArgumentException();
}
if((g = getThreadGroup()) != null) {
if (newPriority > g.getMaxPriority()) {
newPriority = g.getMaxPriority();
}
setPriority0(priority = newPriority);
}
}
需要注意的是:線程優(yōu)先級(jí)不能作為程序正確性的依賴,操作系統(tǒng)有線程優(yōu)先級(jí)的設(shè)定,不以程序設(shè)定的優(yōu)先級(jí)為準(zhǔn)!