本篇文章跟着冰河大佬的思路去阅读Thread源码,我是fw。
Thread类定义
加载本地资源
/* Make sure registerNatives is the first thing <clinit> does. */private static native void registerNatives();static {registerNatives();}
- static代码块执行,在
前 -
成员变量
```java //线程名称 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 为了生成 tid/ private static long threadSeqNumber;
/* Java thread status for tools,
- initialized to indicate thread ‘not yet started’ */ private volatile int threadStatus = 0;
<a name="RLyiP"></a>## 线程的状态定义```javapublic enum State {/*** Thread state for a thread which has not yet started.* 线程没有start();*/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.* 正在运行或等待CPU*/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}.* 1.没有进入synchronized时候* 2.进入synchronized了,之后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;}

构造方法
/*** 自动生成Thread-${nextThreadNum()}的线程名*/public Thread() {init(null, null, "Thread-" + nextThreadNum(), 0);}public Thread(Runnable target) {init(null, target, "Thread-" + nextThreadNum(), 0);}/*** Creates a new Thread that inherits the given AccessControlContext.* This is not a public constructor.* 非public方法*/Thread(Runnable target, AccessControlContext acc) {init(null, target, "Thread-" + nextThreadNum(), 0, acc, false);}/**** @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.* 如果没有设置,则调用 securityManager.getThreadGroup* 没有的话用当前父线程的 Group**/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);}/**** @param stackSize* the desired stack size for the new thread, or zero to indicate* that this parameter is to be ignored.* 这个参数将被忽略*/public Thread(ThreadGroup group, Runnable target, String name,long stackSize) {init(group, target, name, stackSize);}
init()方法
所有的构造方法最终都是调用init()方法实现的。
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");}this.name = name;// 设置ThreadGroupThread parent = currentThread();SecurityManager security = System.getSecurityManager();if (g == null) {/* Determine if it's an applet or not *//* If there is a security manager, ask the security managerwhat to do. */// 优先使用 securityManagerif (security != null) {g = security.getThreadGroup();}/* If the security doesn't have a strong opinion of the matteruse the parent thread group. */// 没有的话再使用父线程的TGif (g == null) {g = parent.getThreadGroup();}}/* checkAccess regardless of whether or not threadgroup isexplicitly 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();elsethis.contextClassLoader = parent.contextClassLoader;this.inheritedAccessControlContext =acc != null ? acc : AccessController.getContext();// runnablethis.target = target;// 设置优先级setPriority(priority);// 取父线程的 inheritableThreadLocalif (inheritThreadLocals && parent.inheritableThreadLocals != null)this.inheritableThreadLocals =ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);/* Stash the specified stack size in case the VM cares */this.stackSize = stackSize;/* Set thread ID 设置线程id */tid = nextThreadID();}
setPriority()方法
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);}}
start()方法
/*** Causes this thread to begin execution; the Java Virtual Machine* calls the <code>run</code> method of this thread.* <p>* The result is that two threads are running concurrently: the* current thread (which returns from the call to the* <code>start</code> method) and the other thread (which executes its* <code>run</code> method).* <p>** It is never legal to start a thread more than once.* In particular, a thread may not be restarted once it has completed* execution.* 一个线程不能重复启用** 如果线程已经start()会报错* @exception IllegalThreadStateException if the thread was already* started.* @see #run()* @see #stop()*/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.* 状态必须为 0* 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();started = true;} finally {try {if (!started) {group.threadStartFailed(this);}} catch (Throwable ignore) {/* do nothing. If start0 threw a Throwable thenit will be passed up the call stack */}}}private native void start0();
sleep()方法
/*** Causes the currently executing thread to sleep (temporarily cease* execution) for the specified number of milliseconds, subject to* the precision and accuracy of system timers and schedulers. The thread* does not lose ownership of any monitors.*** @throws InterruptedException* if any thread has interrupted the current thread. The* <i>interrupted status</i> of the current thread is* cleared when this exception is thrown.*/public static native void sleep(long millis) throws InterruptedException;/*** Causes the currently executing thread to sleep (temporarily cease* execution) for the specified number of milliseconds plus the specified* number of nanoseconds, subject to the precision and accuracy of system* timers and schedulers. The thread does not lose ownership of any* monitors.** 取决于系统计时器和调度程序的精度和准确性。* 线程不会失去任何监视器的所有权。** @param millis* the length of time to sleep in milliseconds** @param nanos* {@code 0-999999} additional nanoseconds to sleep** @throws IllegalArgumentException* if the value of {@code millis} is negative, or the value of* {@code nanos} is not in the range {@code 0-999999}** @throws InterruptedException* if any thread has interrupted the current thread. The* <i>interrupted status</i> of the current thread is* cleared when this exception is thrown.*/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);}
join()方法
/*** Waits at most {@code millis} milliseconds for this thread to* die. A timeout of {@code 0} means to wait forever.* join()-> 会默认调用 join(0) 意味着wait 永久** <p> This implementation uses a loop of {@code this.wait} calls* conditioned on {@code this.isAlive}. As a thread terminates the* {@code this.notifyAll} method is invoked. It is recommended that* applications not use {@code wait}, {@code notify}, or* {@code notifyAll} on {@code Thread} instances.* 实现方式是当前线程如果是isAlive的循环wait,** @param millis* the time to wait in milliseconds** @throws IllegalArgumentException* if the value of {@code millis} is negative** @throws InterruptedException* if any thread has interrupted the current thread. The* <i>interrupted status</i> of the current thread is* cleared when this exception is thrown.*/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 {while (isAlive()) {long delay = millis - now;if (delay <= 0) {break;}wait(delay);now = System.currentTimeMillis() - base;}}}/*** Waits at most {@code millis} milliseconds plus* {@code nanos} nanoseconds for this thread to die.** <p> This implementation uses a loop of {@code this.wait} calls* conditioned on {@code this.isAlive}. As a thread terminates the* {@code this.notifyAll} method is invoked. It is recommended that* applications not use {@code wait}, {@code notify}, or* {@code notifyAll} on {@code Thread} instances.** @param millis* the time to wait in milliseconds** @param nanos* {@code 0-999999} additional nanoseconds to wait** @throws IllegalArgumentException* if the value of {@code millis} is negative, or the value* of {@code nanos} is not in the range {@code 0-999999}** @throws InterruptedException* if any thread has interrupted the current thread. The* <i>interrupted status</i> of the current thread is* cleared when this exception is thrown.*/public final synchronized void join(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++;}join(millis);}/*** Waits for this thread to die.* 调用线程会等待该线程执行完毕,才运行* <p> An invocation of this method behaves in exactly the same* way as the invocation*** @throws InterruptedException* if any thread has interrupted the current thread. The* <i>interrupted status</i> of the current thread is* cleared when this exception is thrown.*/public final void join() throws InterruptedException {join(0);}
interrupt()方法
public void interrupt() {if (this != Thread.currentThread())checkAccess();synchronized (blockerLock) {Interruptible b = blocker;if (b != null) {interrupt0(); // Just to set the interrupt flagb.interrupt(this);return;}}interrupt0();}
Just to set the interrupt flag
suspend()方法
-
stop()方法
```java @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()); }
<a name="LCzMQ"></a># 为什么stop()、resume()、suspend()被弃用<a name="SDH8J"></a>## stop()被舍弃1. 不安全,强制释放所有被锁定的监视器,某些共享数据可能处于不一致状态(转账一半结束了)2. 使用者无感知<a name="lz5Yj"></a>## resume()和suspend()被弃用1. suspend()挂起了线程但是不会释放监视器上持有的锁,导致其他线程无法访问资源2. 恢复目标线程的线程调用resume时,也试图加这个监视器锁,就会死锁手写一个死锁现象```java@Testpublic void testResumeAndSuspendLock() throws InterruptedException {Object o = new Object();Thread thread = new Thread(() -> {synchronized (o){while (true) {System.out.println("hello world");}}});thread.start();TimeUnit.SECONDS.sleep(1);Thread thread1 = new Thread(() -> {synchronized (o) {System.err.println("ee");thread.resume();}});thread1.start();thread.suspend();thread1.join();}
