[toc]
前面已經(jīng)對(duì)java中Thread的生命周期進(jìn)行了分析荤胁,現(xiàn)在看看Thread的源碼。
1.類結(jié)構(gòu)及其成員變量
1.1 類結(jié)構(gòu)
Thread類實(shí)現(xiàn)了Runnable谱净,實(shí)際上我們說過,需要起一個(gè)線程的話擅威,需要繼承Thread或者實(shí)現(xiàn)Runnable接口壕探。實(shí)際上都是實(shí)現(xiàn)了Runnable接口。
/**
* A <i>thread</i> is a thread of execution in a program. The Java
* Virtual Machine allows an application to have multiple threads of
* execution running concurrently.
* <p>
* Every thread has a priority. Threads with higher priority are
* executed in preference to threads with lower priority. Each thread
* may or may not also be marked as a daemon. When code running in
* some thread creates a new <code>Thread</code> object, the new
* thread has its priority initially set equal to the priority of the
* creating thread, and is a daemon thread if and only if the
* creating thread is a daemon.
* <p>
* When a Java Virtual Machine starts up, there is usually a single
* non-daemon thread (which typically calls the method named
* <code>main</code> of some designated class). The Java Virtual
* Machine continues to execute threads until either of the following
* occurs:
* <ul>
* <li>The <code>exit</code> method of class <code>Runtime</code> has been
* called and the security manager has permitted the exit operation
* to take place.
* <li>All threads that are not daemon threads have died, either by
* returning from the call to the <code>run</code> method or by
* throwing an exception that propagates beyond the <code>run</code>
* method.
* </ul>
* <p>
* There are two ways to create a new thread of execution. One is to
* declare a class to be a subclass of <code>Thread</code>. This
* subclass should override the <code>run</code> method of class
* <code>Thread</code>. An instance of the subclass can then be
* allocated and started. For example, a thread that computes primes
* larger than a stated value could be written as follows:
* <hr><blockquote><pre>
* class PrimeThread extends Thread {
* long minPrime;
* PrimeThread(long minPrime) {
* this.minPrime = minPrime;
* }
*
* public void run() {
* // compute primes larger than minPrime
* . . .
* }
* }
* </pre></blockquote><hr>
* <p>
* The following code would then create a thread and start it running:
* <blockquote><pre>
* PrimeThread p = new PrimeThread(143);
* p.start();
* </pre></blockquote>
* <p>
* The other way to create a thread is to declare a class that
* implements the <code>Runnable</code> interface. That class then
* implements the <code>run</code> method. An instance of the class can
* then be allocated, passed as an argument when creating
* <code>Thread</code>, and started. The same example in this other
* style looks like the following:
* <hr><blockquote><pre>
* class PrimeRun implements Runnable {
* long minPrime;
* PrimeRun(long minPrime) {
* this.minPrime = minPrime;
* }
*
* public void run() {
* // compute primes larger than minPrime
* . . .
* }
* }
* </pre></blockquote><hr>
* <p>
* The following code would then create a thread and start it running:
* <blockquote><pre>
* PrimeRun p = new PrimeRun(143);
* new Thread(p).start();
* </pre></blockquote>
* <p>
* Every thread has a name for identification purposes. More than
* one thread may have the same name. If a name is not specified when
* a thread is created, a new name is generated for it.
* <p>
* Unless otherwise noted, passing a {@code null} argument to a constructor
* or method in this class will cause a {@link NullPointerException} to be
* thrown.
*
* @author unascribed
* @see Runnable
* @see Runtime#exit(int)
* @see #run()
* @see #stop()
* @since JDK1.0
*/
public
class Thread implements Runnable {
}
如上是Thread的源碼郊丛。
其注釋大意為:thread是程序中執(zhí)行的線程李请,JVM允許在一個(gè)程序中分配多個(gè)線程并發(fā)執(zhí)行。
每個(gè)線程都有一個(gè)優(yōu)先級(jí)厉熟,具有較高優(yōu)先級(jí)的線程優(yōu)先于優(yōu)先級(jí)較低的線程執(zhí)行导盅,每個(gè)線程也可以標(biāo)記為守護(hù)線程,也可以不標(biāo)記為守護(hù)線程揍瑟。當(dāng)運(yùn)行在某個(gè)線程中的代碼創(chuàng)建一個(gè)新的線程的對(duì)象時(shí)白翻,新的線程優(yōu)先級(jí)最初設(shè)置為與創(chuàng)建的線程的優(yōu)先級(jí)相等。當(dāng)且僅當(dāng)創(chuàng)建線程是守護(hù)線程的時(shí)候绢片,被創(chuàng)建的新線程才是守護(hù)線程滤馍。
當(dāng)jvm啟動(dòng)的時(shí)候,通常有一個(gè)單獨(dú)的非守護(hù)線程底循,通常用調(diào)用main方法所在的類命名巢株。java虛擬機(jī)會(huì)繼續(xù)執(zhí)行線程,直到出現(xiàn)如下情況:
- 運(yùn)行時(shí)Runtime調(diào)用exit方法熙涤,安全管理器允許執(zhí)行退出操作阁苞。
- 所有不是守護(hù)線程的線程都died,要么從調(diào)用run的方法返回祠挫,要么拋出一個(gè)傳播到run方法之外的異常猬错。
通常有兩種方式創(chuàng)建一個(gè)線程,一種是繼承Thread類茸歧,子類應(yīng)該重寫run方法倦炒。然后子類的實(shí)例是可分配的并啟動(dòng)。例如软瞎,計(jì)算質(zhì)數(shù)的線程大于指定值可寫成:
class PrimeThread extends Thread {
long minPrime;
PrimeThread(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
}
然后通過如下代碼來創(chuàng)建線程:
PrimeThread p = new PrimeThread(143);
p.start();
創(chuàng)建線程的另外一種方法是申明一個(gè)類實(shí)現(xiàn)Runnable接口逢唤。然后這個(gè)類實(shí)現(xiàn)run方法拉讯。類的實(shí)例在此后分配,在創(chuàng)建時(shí)做為Thread的參數(shù)傳遞給Thread鳖藕,然后啟動(dòng)魔慷,看起來如下所示:
class PrimeRun implements Runnable {
long minPrime;
PrimeRun(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
}
之后通過如下代碼創(chuàng)建:
PrimeRun p = new PrimeRun(143);
new Thread(p).start();
每個(gè)線程都有一個(gè)用于標(biāo)識(shí)的名稱,超過一個(gè)線程可以有相同的名字著恩,如果名稱未指定時(shí)創(chuàng)建要給線程院尔,將自動(dòng)為其生成一個(gè)新名稱。
1.2 成員變量
其常量區(qū)代碼如下:
private volatile String name;
private int priority;
private Thread threadQ;
private long eetop;
/* Whether or not to single_step this thread. */
private boolean single_step;
/* Whether or not the thread is a daemon thread. */
private boolean daemon = false;
/* JVM state */
private boolean stillborn = false;
/* What will be run. */
private Runnable target;
/* The group of this thread */
private ThreadGroup group;
/* The context ClassLoader for this thread */
private ClassLoader contextClassLoader;
/* The inherited AccessControlContext of this thread */
private AccessControlContext inheritedAccessControlContext;
/* For autonumbering anonymous threads. */
private static int threadInitNumber;
private static synchronized int nextThreadNum() {
return threadInitNumber++;
}
/* ThreadLocal values pertaining to this thread. This map is maintained
* by the ThreadLocal class. */
ThreadLocal.ThreadLocalMap threadLocals = null;
/*
* InheritableThreadLocal values pertaining to this thread. This map is
* maintained by the InheritableThreadLocal class.
*/
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
/*
* The requested stack size for this thread, or 0 if the creator did
* not specify a stack size. It is up to the VM to do whatever it
* likes with this number; some VMs will ignore it.
*/
private long stackSize;
/*
* JVM-private state that persists after native thread termination.
*/
private long nativeParkEventPointer;
/*
* Thread ID
*/
private long tid;
/* For generating thread ID */
private static long threadSeqNumber;
/* Java thread status for tools,
* initialized to indicate thread 'not yet started'
*/
private volatile int threadStatus = 0;
private static synchronized long nextThreadID() {
return ++threadSeqNumber;
}
/**
* The argument supplied to the current call to
* java.util.concurrent.locks.LockSupport.park.
* Set by (private) java.util.concurrent.locks.LockSupport.setBlocker
* Accessed using java.util.concurrent.locks.LockSupport.getBlocker
*/
volatile Object parkBlocker;
/* The object in which this thread is blocked in an interruptible I/O
* operation, if any. The blocker's interrupt method should be invoked
* after setting this thread's interrupt status.
*/
private volatile Interruptible blocker;
其主要成員變量如下:
變量名 | 類型 | 說明 |
---|---|---|
name | volatile String | 線程名稱 |
priority | int | 線程的優(yōu)先級(jí)喉誊,默認(rèn)為5邀摆,范圍1-10 |
threadQ | Thread | |
eetop | long | |
single_step | boolean | 是否單步執(zhí)行 |
daemon | boolean | 守護(hù)線程狀態(tài),默認(rèn)為false |
stillborn | boolean | JVM狀態(tài)伍茄,默認(rèn)為false |
target | target | 將被執(zhí)行的Runnable實(shí)現(xiàn)類 |
group | ThreadGroup | 當(dāng)前線程的線程組 |
contextClassLoader | ClassLoader | 這個(gè)線程上下文的類加載器 |
inheritedAccessControlContext | AccessControlContext | 該線程繼承的AccessControlContext |
threadInitNumber | static int | 用于匿名線程的自動(dòng)編號(hào) |
threadLocals | ThreadLocal.ThreadLocalMap | 屬于此線程的ThreadLocal,這個(gè)映射關(guān)系通過ThreadLocal維持 |
inheritableThreadLocals | ThreadLocal.ThreadLocalMap | 這個(gè)線程的InheritableThreadLocal栋盹,其映射關(guān)系通過InheritableThreadLocal維持 |
stackSize | long | 此線程的請(qǐng)求的堆棧的大小,如果創(chuàng)建者的請(qǐng)求堆棧大小為0敷矫,則不指定堆棧大小例获,由jvm來自行決定。一些jvm會(huì)忽略這個(gè)參數(shù)曹仗。 |
nativeParkEventPointer | long | 在本機(jī)線程終止后持續(xù)存在的jvm私有狀態(tài)榨汤。 |
tid | long | 線程的ID |
threadSeqNumber | static long | 用于生成線程的ID |
threadStatus | volatile int | java線程狀態(tài),0表示未啟動(dòng) |
parkBlocker | volatile Object | 提供給LockSupport調(diào)用的參數(shù) |
blocker | volatile Interruptible | 此線程在可中斷的IO操作中被阻塞的對(duì)象怎茫,阻塞程序的中斷方法應(yīng)該在設(shè)置了這個(gè)線程中斷狀態(tài)之后被調(diào)用 |
1.3 常量
/**
* The minimum priority that a thread can have.
*/
public final static int MIN_PRIORITY = 1;
/**
* The default priority that is assigned to a thread.
*/
public final static int NORM_PRIORITY = 5;
/**
* The maximum priority that a thread can have.
*/
public final static int MAX_PRIORITY = 10;
實(shí)際上這些常量值是對(duì)于線程優(yōu)先級(jí)的常量件余,最小為1,最大為10遭居,默認(rèn)值為5。操作系統(tǒng)在線程在運(yùn)行的過程中會(huì)按照優(yōu)先級(jí)來分配時(shí)間片旬渠。
2.構(gòu)造方法
2.1 Thread()
空構(gòu)造函數(shù)俱萍,發(fā)呢配一個(gè)新的Thread對(duì)象,實(shí)際上是調(diào)用的init方法告丢。由于Thread大部分代碼都是native來實(shí)現(xiàn)枪蘑,因此這個(gè)構(gòu)造函數(shù)是通過改變前面的成員變量來實(shí)現(xiàn)對(duì)Thread各種行為的改變。
/**
* Allocates a new {@code Thread} object. This constructor has the same
* effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
* {@code (null, null, gname)}, where {@code gname} is a newly generated
* name. Automatically generated names are of the form
* {@code "Thread-"+}<i>n</i>, where <i>n</i> is an integer.
*/
public Thread() {
init(null, null, "Thread-" + nextThreadNum(), 0);
}
2.2 Thread(Runnable target)
/**
* Allocates a new {@code Thread} object. This constructor has the same
* effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
* {@code (null, target, gname)}, where {@code gname} is a newly generated
* name. Automatically generated names are of the form
* {@code "Thread-"+}<i>n</i>, where <i>n</i> is an integer.
*
* @param target
* the object whose {@code run} method is invoked when this thread
* is started. If {@code null}, this classes {@code run} method does
* nothing.
*/
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
此方法是我們通常用Runnable啟動(dòng)線程的方法岖免。
實(shí)際上我們穿入的Runnable對(duì)象岳颇,被放置在了target變量中,之后通過后jvm中啟動(dòng)線程|
2.3 Thread(Runnable target, AccessControlContext acc)
/**
* Creates a new Thread that inherits the given AccessControlContext.
* This is not a public constructor.
*/
Thread(Runnable target, AccessControlContext acc) {
init(null, target, "Thread-" + nextThreadNum(), 0, acc, false);
}
在傳入Runnable的時(shí)候還可以指定AccessControlContext颅湘。
2.4 Thread(ThreadGroup group, Runnable target)
/**
* Allocates a new {@code Thread} object. This constructor has the same
* effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
* {@code (group, target, gname)} ,where {@code gname} is a newly generated
* name. Automatically generated names are of the form
* {@code "Thread-"+}<i>n</i>, where <i>n</i> is an integer.
*
* @param group
* the thread group. If {@code null} and there is a security
* manager, the group is determined by {@linkplain
* SecurityManager#getThreadGroup SecurityManager.getThreadGroup()}.
* If there is not a security manager or {@code
* SecurityManager.getThreadGroup()} returns {@code null}, the group
* is set to the current thread's thread group.
*
* @param target
* the object whose {@code run} method is invoked when this thread
* is started. If {@code null}, this thread's run method is invoked.
*
* @throws SecurityException
* if the current thread cannot create a thread in the specified
* thread group
*/
public Thread(ThreadGroup group, Runnable target) {
init(group, target, "Thread-" + nextThreadNum(), 0);
}
使用線程組ThreadGroup话侧。如果有安全管理器,則線程由安全管理器返回 SecurityManager.getThreadGroup()闯参。如果沒有安全管理器或者SecurityManager.getThreadGroup()返回為空瞻鹏,則返回當(dāng)前的線程組悲立。
2.5 Thread(String name)
指定線程的名稱:
/**
* Allocates a new {@code Thread} object. This constructor has the same
* effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
* {@code (null, null, name)}.
*
* @param name
* the name of the new thread
*/
public Thread(String name) {
init(null, null, name, 0);
}
2.6 Thread(ThreadGroup group, String name)
/**
* Allocates a new {@code Thread} object. This constructor has the same
* effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
* {@code (group, null, name)}.
*
* @param group
* the thread group. If {@code null} and there is a security
* manager, the group is determined by {@linkplain
* SecurityManager#getThreadGroup SecurityManager.getThreadGroup()}.
* If there is not a security manager or {@code
* SecurityManager.getThreadGroup()} returns {@code null}, the group
* is set to the current thread's thread group.
*
* @param name
* the name of the new thread
*
* @throws SecurityException
* if the current thread cannot create a thread in the specified
* thread group
*/
public Thread(ThreadGroup group, String name) {
init(group, null, name, 0);
}
2.7 Thread(Runnable target, String name)
/**
* Allocates a new {@code Thread} object. This constructor has the same
* effect as {@linkplain #Thread(ThreadGroup,Runnable,String) Thread}
* {@code (null, target, name)}.
*
* @param target
* the object whose {@code run} method is invoked when this thread
* is started. If {@code null}, this thread's run method is invoked.
*
* @param name
* the name of the new thread
*/
public Thread(Runnable target, String name) {
init(null, target, name, 0);
}
通過Runnable并指定線程的name。
2.8 Thread(ThreadGroup group, Runnable target, String name)
public Thread(ThreadGroup group, Runnable target, String name) {
init(group, target, name, 0);
}
2.9 Thread(ThreadGroup group, Runnable target, String name,long stackSize)
public Thread(ThreadGroup group, Runnable target, String name,
long stackSize) {
init(group, target, name, stackSize);
}
分配一個(gè)線程新博,使其將target做為目標(biāo)對(duì)象薪夕,具有name指定的名稱,和group指定的線程組赫悄。其中原献,指定StackSize參數(shù)能夠決定其for循環(huán)棧的深度,但是這也由JVM決定埂淮,某些JVM這個(gè)參數(shù)并不能生效姑隅。
JVM可以自由的處理stackSize的參數(shù)做為建議值,如果指定的值低得不合理同诫,那么可以使用jvm平臺(tái)的最小值粤策。如果值太高,則可能會(huì)使用平臺(tái)缺省的最大值误窖。虛擬機(jī)可以自由地四舍五入指定的值叮盘,讓到JVM認(rèn)為是合適的值。
stackSize參數(shù)為0則會(huì)導(dǎo)致其與Thread(ThreadGroup, Runnable, String)構(gòu)造器完全一致霹俺。
由于這個(gè)特性依賴于JVM平臺(tái)柔吼,因此在使用的時(shí)候要特別小心,給定線程的stackSize可能因?yàn)榫€程對(duì)峙的大小造成不同JRE實(shí)現(xiàn)有所不同丙唧。鑒于此愈魏,可能需要仔細(xì)調(diào)整堆棧的大小參數(shù),根據(jù)JRE要運(yùn)行程序的實(shí)際情況進(jìn)行調(diào)優(yōu)想际。
3. native方法
由于Thread大部分邏輯都是由JVM完成培漏,因此核心的方法都是native方法。
//確保registerNatives是<clinit>做的第一件事,這個(gè)代碼要放在代碼的最前面胡本。
private static native void registerNatives();
//返回當(dāng)前線程
public static native Thread currentThread();
//當(dāng)前線程在獲取CPU執(zhí)行權(quán)之后牌柄,讓出,之后讓等待隊(duì)列的線程重新競(jìng)爭(zhēng)侧甫。有可能是當(dāng)前線程再次搶到執(zhí)行權(quán)珊佣,也有可能是其他線程。
public static native void yield();
//休眠
public static native void sleep(long millis) throws InterruptedException;
//啟動(dòng)
private native void start0();
//測(cè)試某個(gè)值是否被中斷 中斷狀態(tài)根據(jù)傳入的ClearInterrupted值進(jìn)行重置
private native boolean isInterrupted(boolean ClearInterrupted);
//測(cè)試線程是否是存活狀態(tài)
public final native boolean isAlive();
//計(jì)算線程中的堆棧數(shù)披粟,此線程必須被暫停 咒锻,這個(gè)方法已不再建議使用
public native int countStackFrames();
//當(dāng)且僅當(dāng)當(dāng)前線程在指定的對(duì)象上保持監(jiān)視器鎖時(shí),才返回 true守屉。
public static native boolean holdsLock(Object obj);
//導(dǎo)出線程堆棧信息
private native static StackTraceElement[][] dumpThreads(Thread[] threads);
//get線程
private native static Thread[] getThreads();
//設(shè)置優(yōu)先級(jí)
private native void setPriority0(int newPriority);
//停止
private native void stop0(Object o);
//掛起
private native void suspend0();
//重置
private native void resume0();
//中斷
private native void interrupt0();
//設(shè)置線程名稱
private native void setNativeName(String name);
4.重要的非native方法
4.1 init
線程初始化方法
private void init(ThreadGroup g, Runnable target, String name,
long stackSize, AccessControlContext acc,
boolean inheritThreadLocals) {
//name如果為空惑艇,則返回異常,實(shí)際上name在其他方法中如果不指定會(huì)自動(dòng)生成拇泛,通常為"Thread-" + nextThreadNum()
if (name == null) {
throw new NullPointerException("name cannot be null");
}
this.name = name;
//指定父線程
Thread parent = currentThread();
//安全管理器
SecurityManager security = System.getSecurityManager();
//如果線程組為null
if (g == null) {
/* Determine if it's an applet or not */
/* If there is a security manager, ask the security manager
what to do. */
if (security != null) {
g = security.getThreadGroup();
}
/* If the security doesn't have a strong opinion of the matter
use the parent thread group. */
if (g == null) {
//線程組為空的話敦捧,g為parent的線程組
g = parent.getThreadGroup();
}
}
/* checkAccess regardless of whether or not threadgroup is
explicitly passed in. */
g.checkAccess();
/*
* Do we have the required permissions?
*/
//如果安全管理器為空
if (security != null) {
if (isCCLOverridden(getClass())) {
security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
}
}
g.addUnstarted();
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;
setPriority(priority);
if (inheritThreadLocals && parent.inheritableThreadLocals != null)
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
/* Stash the specified stack size in case the VM cares */
//指定stackSize
this.stackSize = stackSize;
/* Set thread ID */
//指定線程id
tid = nextThreadID();
}
4.2 start
線程啟動(dòng)的方法:
public synchronized void start() {
/**
* This method is not invoked for the main method thread or "system"
* group threads created/set up by the VM. Any new functionality added
* to this method in the future may have to also be added to the VM.
*
* A zero status value corresponds to state "NEW".
*/
if (threadStatus != 0)
throw new IllegalThreadStateException();
/* Notify the group that this thread is about to be started
* so that it can be added to the group's list of threads
* and the group's unstarted count can be decremented. */
group.add(this);
boolean started = false;
try {
//實(shí)際上調(diào)用的native方法
start0();
//之后修改start的狀態(tài)
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
/* do nothing. If start0 threw a Throwable then
it will be passed up the call stack */
}
}
}
4.3 setDaemon
設(shè)置守護(hù)線程狀態(tài):
public final void setDaemon(boolean on) {
checkAccess();
if (isAlive()) {
throw new IllegalThreadStateException();
}
daemon = on;
}
4.4 checkAccess
檢查訪問狀態(tài):
public final void checkAccess() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkAccess(this);
}
}
4.5 join
join將當(dāng)前運(yùn)行的線程阻塞须板,之后讓join的持有線程執(zhí)行完之后再繼續(xù)執(zhí)行。等待時(shí)間為傳入的參數(shù)兢卵。
public final synchronized void join(long millis)
throws InterruptedException {
//獲得當(dāng)前時(shí)間
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
//如果當(dāng)前線程可用习瑰,則調(diào)用wait
while (isAlive()) {
wait(0);
}
} else {
通過wait方法delay。
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
這個(gè)方法提供給另外兩個(gè)方法調(diào)用:
public final synchronized void join(long millis, int nanos) throws InterruptedException;
public final void join() throws InterruptedException;
其中wait(0)的話秽荤,則會(huì)一直阻塞甜奄,直到notify才會(huì)返回。不難發(fā)現(xiàn)窃款,join方法底層實(shí)際上是wait方法课兄。
4.6 sleep
sleep方法通過native方法實(shí)現(xiàn)晨继。
public static void sleep(long millis, int nanos)
throws InterruptedException {
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (nanos < 0 || nanos > 999999) {
throw new IllegalArgumentException(
"nanosecond timeout value out of range");
}
if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
millis++;
}
sleep(millis);
}
其中只是判斷了值的范圍紊扬。
4.7 interrupt
public void interrupt() {
if (this != Thread.currentThread())
checkAccess();
鎖定之后調(diào)用interrupt0
synchronized (blockerLock) {
Interruptible b = blocker;
//如果b不為null則返回
if (b != null) {
interrupt0(); // Just to set the interrupt flag
b.interrupt(this);
return;
}
}
//當(dāng)b為空的情況確保interrupt0一定會(huì)被執(zhí)行蜒茄。
interrupt0();
}
4.8 stop方法
stop方法已經(jīng)過時(shí),不再采用這個(gè)方法停止線程檀葛,這是因?yàn)楦顾酰瑂top方法非常粗暴屿聋,會(huì)導(dǎo)致很多問題,后面詳細(xì)分析藏鹊。
@Deprecated
public final void stop() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
checkAccess();
if (this != Thread.currentThread()) {
security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION);
}
}
// A zero status value corresponds to "NEW", it can't change to
// not-NEW because we hold the lock.
if (threadStatus != 0) {
resume(); // Wake up thread if it was suspended; no-op otherwise
}
// The VM can handle all thread states
stop0(new ThreadDeath());
}
5.內(nèi)部類
5.1 Caches
cache緩存了子類安全審計(jì)的結(jié)果。如果未來要進(jìn)行使用楚殿,采用ConcurrentReferenceHashMap替換宴抚。
/** cache of subclass security audit results */
/* Replace with ConcurrentReferenceHashMap when/if it appears in a future
* release */
private static class Caches {
//緩存子類安全審計(jì)結(jié)果
/** cache of subclass security audit results */
static final ConcurrentMap<WeakClassKey,Boolean> subclassAudits =
new ConcurrentHashMap<>();
//對(duì)審計(jì)子類的weak引用進(jìn)行排隊(duì)
/** queue for WeakReferences to audited subclasses */
static final ReferenceQueue<Class<?>> subclassAuditsQueue =
new ReferenceQueue<>();
}
5.2 WeakClassKey
弱引用對(duì)象的key菇曲。
/**
* Weak key for Class objects.
**/
static class WeakClassKey extends WeakReference<Class<?>> {
/**
* saved value of the referent's identity hash code, to maintain
* a consistent hash code after the referent has been cleared
*/
private final int hash;
/**
* Create a new WeakClassKey to the given object, registered
* with a queue.
*/
WeakClassKey(Class<?> cl, ReferenceQueue<Class<?>> refQueue) {
super(cl, refQueue);
hash = System.identityHashCode(cl);
}
/**
* Returns the identity hash code of the original referent.
*/
@Override
public int hashCode() {
return hash;
}
/**
* Returns true if the given object is this identical
* WeakClassKey instance, or, if this object's referent has not
* been cleared, if the given object is another WeakClassKey
* instance with the identical non-null referent as this one.
*/
@Override
public boolean equals(Object obj) {
if (obj == this)
return true;
if (obj instanceof WeakClassKey) {
Object referent = get();
return (referent != null) &&
(referent == ((WeakClassKey) obj).get());
} else {
return false;
}
}
}
5.3 State
線程的狀態(tài)內(nèi)部枚舉類常潮。這個(gè)線程的狀態(tài)有NEW楷力、RUNNABLE孵户、BLOCKED夏哭、WAITING献联、TIMED_WAITING、TERMINATED狀態(tài)进胯。
public enum State {
/**
* Thread state for a thread which has not yet started.
*/
NEW,
/**
* Thread state for a runnable thread. A thread in the runnable
* state is executing in the Java virtual machine but it may
* be waiting for other resources from the operating system
* such as processor.
*/
RUNNABLE,
/**
* Thread state for a thread blocked waiting for a monitor lock.
* A thread in the blocked state is waiting for a monitor lock
* to enter a synchronized block/method or
* reenter a synchronized block/method after calling
* {@link Object#wait() Object.wait}.
*/
BLOCKED,
/**
* Thread state for a waiting thread.
* A thread is in the waiting state due to calling one of the
* following methods:
* <ul>
* <li>{@link Object#wait() Object.wait} with no timeout</li>
* <li>{@link #join() Thread.join} with no timeout</li>
* <li>{@link LockSupport#park() LockSupport.park}</li>
* </ul>
*
* <p>A thread in the waiting state is waiting for another thread to
* perform a particular action.
*
* For example, a thread that has called <tt>Object.wait()</tt>
* on an object is waiting for another thread to call
* <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
* that object. A thread that has called <tt>Thread.join()</tt>
* is waiting for a specified thread to terminate.
*/
WAITING,
/**
* Thread state for a waiting thread with a specified waiting time.
* A thread is in the timed waiting state due to calling one of
* the following methods with a specified positive waiting time:
* <ul>
* <li>{@link #sleep Thread.sleep}</li>
* <li>{@link Object#wait(long) Object.wait} with timeout</li>
* <li>{@link #join(long) Thread.join} with timeout</li>
* <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
* <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
* </ul>
*/
TIMED_WAITING,
/**
* Thread state for a terminated thread.
* The thread has completed execution.
*/
TERMINATED;
}
狀態(tài)的詳細(xì)描述在前面文章中已經(jīng)詳細(xì)介紹。我們重點(diǎn)需要關(guān)注這些狀態(tài)的轉(zhuǎn)換:
6.總結(jié)
本文分析了Thread的源碼盯漂。我們可以看出署隘,實(shí)際上join方法實(shí)際上底層是采用了synchronized和Object的wait方法。另外违崇,停止線程的stop方法已經(jīng)棄用诊霹,我們應(yīng)該用interrupt()方法。
stop和interrupt方法區(qū)別在于:
stop方法會(huì)立即殺死線程伴箩,不給線程任何暫停的機(jī)會(huì)鄙漏,一旦線程持有Lock怔蚌,那么線程就來不及調(diào)用unlock方法,這樣就導(dǎo)致其他線程再也不可能獲得這個(gè)鎖椅野。這是非常危險(xiǎn)的操作,也是為什么stop方法會(huì)被棄用的原因离福。
interrupt方法則僅僅只是通知線程炼蛤,線程可以繼續(xù)執(zhí)行后續(xù)操作,interrupt實(shí)際上是一個(gè)異常檢測(cè)的流程赠涮。當(dāng)線程 處于 WAITING暗挑、TIMED_WAITING 狀態(tài)時(shí)炸裆,如果其他線程調(diào)用線程的 interrupt() 方法,會(huì)使線程返回到 RUNNABLE 狀態(tài)国拇,同時(shí)線程 的代碼會(huì)觸發(fā) InterruptedException 異常惯殊。
此外還有一種主動(dòng)檢測(cè)機(jī)制,就是通過調(diào)用isInterrupted()方法务热。
最后己儒,我們需要重點(diǎn)掌握線程模型中的6個(gè)狀態(tài)及其轉(zhuǎn)換的過程闪湾。這也是我們學(xué)習(xí)線程的重點(diǎn)。