本篇文章跟着冰河大佬的思路去阅读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>
## 线程的状态定义
```java
public 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;
// 设置ThreadGroup
Thread 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 manager
what to do. */
// 优先使用 securityManager
if (security != null) {
g = security.getThreadGroup();
}
/* If the security doesn't have a strong opinion of the matter
use the parent thread group. */
// 没有的话再使用父线程的TG
if (g == null) {
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();
// runnable
this.target = target;
// 设置优先级
setPriority(priority);
// 取父线程的 inheritableThreadLocal
if (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 then
it 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 flag
b.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
@Test
public 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();
}