[toc]
前面已经对java中Thread的生命周期进行了分析,现在看看Thread的源码。
1.类结构及其成员变量
1.1 类结构
Thread类实现了Runnable,实际上我们说过,需要起一个线程的话,需要继承Thread或者实现Runnable接口。实际上都是实现了Runnable接口。
/**
* A thread is a thread of execution in a program. The Java
* Virtual Machine allows an application to have multiple threads of
* execution running concurrently.
*
* 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 Thread
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.
*
* When a Java Virtual Machine starts up, there is usually a single
* non-daemon thread (which typically calls the method named
* main
of some designated class). The Java Virtual
* Machine continues to execute threads until either of the following
* occurs:
*
* - The
exit
method of class Runtime
has been
* called and the security manager has permitted the exit operation
* to take place.
* - All threads that are not daemon threads have died, either by
* returning from the call to the
run
method or by
* throwing an exception that propagates beyond the run
* method.
*
*
* There are two ways to create a new thread of execution. One is to
* declare a class to be a subclass of Thread
. This
* subclass should override the run
method of class
* Thread
. 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:
*
* class PrimeThread extends Thread {
* long minPrime;
* PrimeThread(long minPrime) {
* this.minPrime = minPrime;
* }
*
* public void run() {
* // compute primes larger than minPrime
* . . .
* }
* }
*
*
* The following code would then create a thread and start it running:
*
* PrimeThread p = new PrimeThread(143);
* p.start();
*
*
* The other way to create a thread is to declare a class that
* implements the Runnable
interface. That class then
* implements the run
method. An instance of the class can
* then be allocated, passed as an argument when creating
* Thread
, and started. The same example in this other
* style looks like the following:
*
* class PrimeRun implements Runnable {
* long minPrime;
* PrimeRun(long minPrime) {
* this.minPrime = minPrime;
* }
*
* public void run() {
* // compute primes larger than minPrime
* . . .
* }
* }
*
*
* The following code would then create a thread and start it running:
*
* PrimeRun p = new PrimeRun(143);
* new Thread(p).start();
*
*
* 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.
*
* 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是程序中执行的线程,JVM允许在一个程序中分配多个线程并发执行。
每个线程都有一个优先级,具有较高优先级的线程优先于优先级较低的线程执行,每个线程也可以标记为守护线程,也可以不标记为守护线程。当运行在某个线程中的代码创建一个新的线程的对象时,新的线程优先级最初设置为与创建的线程的优先级相等。当且仅当创建线程是守护线程的时候,被创建的新线程才是守护线程。
当jvm启动的时候,通常有一个单独的非守护线程,通常用调用main方法所在的类命名。java虚拟机会继续执行线程,直到出现如下情况:
- 运行时Runtime调用exit方法,安全管理器允许执行退出操作。
- 所有不是守护线程的线程都died,要么从调用run的方法返回,要么抛出一个传播到run方法之外的异常。
通常有两种方式创建一个线程,一种是继承Thread类,子类应该重写run方法。然后子类的实例是可分配的并启动。例如,计算质数的线程大于指定值可写成:
class PrimeThread extends Thread {
long minPrime;
PrimeThread(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
}
然后通过如下代码来创建线程:
PrimeThread p = new PrimeThread(143);
p.start();
创建线程的另外一种方法是申明一个类实现Runnable接口。然后这个类实现run方法。类的实例在此后分配,在创建时做为Thread的参数传递给Thread,然后启动,看起来如下所示:
class PrimeRun implements Runnable {
long minPrime;
PrimeRun(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
}
之后通过如下代码创建:
PrimeRun p = new PrimeRun(143);
new Thread(p).start();
每个线程都有一个用于标识的名称,超过一个线程可以有相同的名字,如果名称未指定时创建要给线程,将自动为其生成一个新名称。
1.2 成员变量
其常量区代码如下:
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 | 线程的优先级,默认为5,范围1-10 |
threadQ | Thread | |
eetop | long | |
single_step | boolean | 是否单步执行 |
daemon | boolean | 守护线程状态,默认为false |
stillborn | boolean | JVM状态,默认为false |
target | target | 将被执行的Runnable实现类 |
group | ThreadGroup | 当前线程的线程组 |
contextClassLoader | ClassLoader | 这个线程上下文的类加载器 |
inheritedAccessControlContext | AccessControlContext | 该线程继承的AccessControlContext |
threadInitNumber | static int | 用于匿名线程的自动编号 |
threadLocals | ThreadLocal.ThreadLocalMap | 属于此线程的ThreadLocal,这个映射关系通过ThreadLocal维持 |
inheritableThreadLocals | ThreadLocal.ThreadLocalMap | 这个线程的InheritableThreadLocal,其映射关系通过InheritableThreadLocal维持 |
stackSize | long | 此线程的请求的堆栈的大小,如果创建者的请求堆栈大小为0,则不指定堆栈大小,由jvm来自行决定。一些jvm会忽略这个参数。 |
nativeParkEventPointer | long | 在本机线程终止后持续存在的jvm私有状态。 |
tid | long | 线程的ID |
threadSeqNumber | static long | 用于生成线程的ID |
threadStatus | volatile int | java线程状态,0表示未启动 |
parkBlocker | volatile Object | 提供给LockSupport调用的参数 |
blocker | volatile Interruptible | 此线程在可中断的IO操作中被阻塞的对象,阻塞程序的中断方法应该在设置了这个线程中断状态之后被调用 |
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;
实际上这些常量值是对于线程优先级的常量,最小为1,最大为10,默认值为5。操作系统在线程在运行的过程中会按照优先级来分配时间片。
2.构造方法
2.1 Thread()
空构造函数,发呢配一个新的Thread对象,实际上是调用的init方法。由于Thread大部分代码都是native来实现,因此这个构造函数是通过改变前面的成员变量来实现对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-"+}n, where n 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-"+}n, where n 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启动线程的方法。
实际上我们穿入的Runnable对象,被放置在了target变量中,之后通过后jvm中启动线程|
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的时候还可以指定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-"+}n, where n 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()返回为空,则返回当前的线程组。
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);
}
分配一个线程,使其将target做为目标对象,具有name指定的名称,和group指定的线程组。其中,指定StackSize参数能够决定其for循环栈的深度,但是这也由JVM决定,某些JVM这个参数并不能生效。
JVM可以自由的处理stackSize的参数做为建议值,如果指定的值低得不合理,那么可以使用jvm平台的最小值。如果值太高,则可能会使用平台缺省的最大值。虚拟机可以自由地四舍五入指定的值,让到JVM认为是合适的值。
stackSize参数为0则会导致其与Thread(ThreadGroup, Runnable, String)构造器完全一致。
由于这个特性依赖于JVM平台,因此在使用的时候要特别小心,给定线程的stackSize可能因为线程对峙的大小造成不同JRE实现有所不同。鉴于此,可能需要仔细调整堆栈的大小参数,根据JRE要运行程序的实际情况进行调优。
3. native方法
由于Thread大部分逻辑都是由JVM完成,因此核心的方法都是native方法。
//确保registerNatives是做的第一件事,这个代码要放在代码的最前面。
private static native void registerNatives();
//返回当前线程
public static native Thread currentThread();
//当前线程在获取CPU执行权之后,让出,之后让等待队列的线程重新竞争。有可能是当前线程再次抢到执行权,也有可能是其他线程。
public static native void yield();
//休眠
public static native void sleep(long millis) throws InterruptedException;
//启动
private native void start0();
//测试某个值是否被中断 中断状态根据传入的ClearInterrupted值进行重置
private native boolean isInterrupted(boolean ClearInterrupted);
//测试线程是否是存活状态
public final native boolean isAlive();
//计算线程中的堆栈数,此线程必须被暂停 ,这个方法已不再建议使用
public native int countStackFrames();
//当且仅当当前线程在指定的对象上保持监视器锁时,才返回 true。
public static native boolean holdsLock(Object obj);
//导出线程堆栈信息
private native static StackTraceElement[][] dumpThreads(Thread[] threads);
//get线程
private native static Thread[] getThreads();
//设置优先级
private native void setPriority0(int newPriority);
//停止
private native void stop0(Object o);
//挂起
private native void suspend0();
//重置
private native void resume0();
//中断
private native void interrupt0();
//设置线程名称
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如果为空,则返回异常,实际上name在其他方法中如果不指定会自动生成,通常为"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
线程启动的方法:
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 {
//实际上调用的native方法
start0();
//之后修改start的状态
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
设置守护线程状态:
public final void setDaemon(boolean on) {
checkAccess();
if (isAlive()) {
throw new IllegalThreadStateException();
}
daemon = on;
}
4.4 checkAccess
检查访问状态:
public final void checkAccess() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkAccess(this);
}
}
4.5 join
join将当前运行的线程阻塞,之后让join的持有线程执行完之后再继续执行。等待时间为传入的参数。
public final synchronized void join(long millis)
throws InterruptedException {
//获得当前时间
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
//如果当前线程可用,则调用wait
while (isAlive()) {
wait(0);
}
} else {
通过wait方法delay。
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
这个方法提供给另外两个方法调用:
public final synchronized void join(long millis, int nanos) throws InterruptedException;
public final void join() throws InterruptedException;
其中wait(0)的话,则会一直阻塞,直到notify才会返回。不难发现,join方法底层实际上是wait方法。
4.6 sleep
sleep方法通过native方法实现。
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();
锁定之后调用interrupt0
synchronized (blockerLock) {
Interruptible b = blocker;
//如果b不为null则返回
if (b != null) {
interrupt0(); // Just to set the interrupt flag
b.interrupt(this);
return;
}
}
//当b为空的情况确保interrupt0一定会被执行。
interrupt0();
}
4.8 stop方法
stop方法已经过时,不再采用这个方法停止线程,这是因为,stop方法非常粗暴,会导致很多问题,后面详细分析。
@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.内部类
5.1 Caches
cache缓存了子类安全审计的结果。如果未来要进行使用,采用ConcurrentReferenceHashMap替换。
/** cache of subclass security audit results */
/* Replace with ConcurrentReferenceHashMap when/if it appears in a future
* release */
private static class Caches {
//缓存子类安全审计结果
/** cache of subclass security audit results */
static final ConcurrentMap subclassAudits =
new ConcurrentHashMap<>();
//对审计子类的weak引用进行排队
/** queue for WeakReferences to audited subclasses */
static final ReferenceQueue> subclassAuditsQueue =
new ReferenceQueue<>();
}
5.2 WeakClassKey
弱引用对象的key。
/**
* Weak key for Class objects.
**/
static class WeakClassKey extends WeakReference> {
/**
* 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> 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
线程的状态内部枚举类。这个线程的状态有NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED状态。
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:
*
* - {@link Object#wait() Object.wait} with no timeout
* - {@link #join() Thread.join} with no timeout
* - {@link LockSupport#park() LockSupport.park}
*
*
* A thread in the waiting state is waiting for another thread to
* perform a particular action.
*
* For example, a thread that has called Object.wait()
* on an object is waiting for another thread to call
* Object.notify() or Object.notifyAll() on
* that object. A thread that has called Thread.join()
* 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:
*
* - {@link #sleep Thread.sleep}
* - {@link Object#wait(long) Object.wait} with timeout
* - {@link #join(long) Thread.join} with timeout
* - {@link LockSupport#parkNanos LockSupport.parkNanos}
* - {@link LockSupport#parkUntil LockSupport.parkUntil}
*
*/
TIMED_WAITING,
/**
* Thread state for a terminated thread.
* The thread has completed execution.
*/
TERMINATED;
}
状态的详细描述在前面文章中已经详细介绍。我们重点需要关注这些状态的转换:
6.总结
本文分析了Thread的源码。我们可以看出,实际上join方法实际上底层是采用了synchronized和Object的wait方法。另外,停止线程的stop方法已经弃用,我们应该用interrupt()方法。
stop和interrupt方法区别在于:
stop方法会立即杀死线程,不给线程任何暂停的机会,一旦线程持有Lock,那么线程就来不及调用unlock方法,这样就导致其他线程再也不可能获得这个锁。这是非常危险的操作,也是为什么stop方法会被弃用的原因。
interrupt方法则仅仅只是通知线程,线程可以继续执行后续操作,interrupt实际上是一个异常检测的流程。当线程 处于 WAITING、TIMED_WAITING 状态时,如果其他线程调用线程的 interrupt() 方法,会使线程返回到 RUNNABLE 状态,同时线程 的代码会触发 InterruptedException 异常。
此外还有一种主动检测机制,就是通过调用isInterrupted()方法。
最后,我们需要重点掌握线程模型中的6个状态及其转换的过程。这也是我们学习线程的重点。