1. 本篇文章跟着冰河大佬的思路去阅读Thread源码,我是fw

Thread类定义

加载本地资源

  1. /* Make sure registerNatives is the first thing <clinit> does. */
  2. private static native void registerNatives();
  3. static {
  4. registerNatives();
  5. }
  • 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;
  1. <a name="RLyiP"></a>
  2. ## 线程的状态定义
  3. ```java
  4. public enum State {
  5. /**
  6. * Thread state for a thread which has not yet started.
  7. * 线程没有start();
  8. */
  9. NEW,
  10. /**
  11. * Thread state for a runnable thread. A thread in the runnable
  12. * state is executing in the Java virtual machine but it may
  13. * be waiting for other resources from the operating system
  14. * such as processor.
  15. * 正在运行或等待CPU
  16. */
  17. RUNNABLE,
  18. /**
  19. * Thread state for a thread blocked waiting for a monitor lock.
  20. * A thread in the blocked state is waiting for a monitor lock
  21. * to enter a synchronized block/method or
  22. * reenter a synchronized block/method after calling
  23. * {@link Object#wait() Object.wait}.
  24. * 1.没有进入synchronized时候
  25. * 2.进入synchronized了,之后wait,但是又被唤醒,唤醒后有没抢到锁
  26. *
  27. */
  28. BLOCKED,
  29. /**
  30. * Thread state for a waiting thread.
  31. * A thread is in the waiting state due to calling one of the
  32. * following methods:
  33. * <ul>
  34. * <li>{@link Object#wait() Object.wait} with no timeout</li>
  35. * <li>{@link #join() Thread.join} with no timeout</li>
  36. * <li>{@link LockSupport#park() LockSupport.park}</li>
  37. * </ul>
  38. *
  39. * <p>A thread in the waiting state is waiting for another thread to
  40. * perform a particular action.
  41. *
  42. * For example, a thread that has called <tt>Object.wait()</tt>
  43. * on an object is waiting for another thread to call
  44. * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
  45. * that object. A thread that has called <tt>Thread.join()</tt>
  46. * is waiting for a specified thread to terminate.
  47. */
  48. WAITING,
  49. /**
  50. * Thread state for a waiting thread with a specified waiting time.
  51. * A thread is in the timed waiting state due to calling one of
  52. * the following methods with a specified positive waiting time:
  53. * <ul>
  54. * <li>{@link #sleep Thread.sleep}</li>
  55. * <li>{@link Object#wait(long) Object.wait} with timeout</li>
  56. * <li>{@link #join(long) Thread.join} with timeout</li>
  57. * <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
  58. * <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
  59. * </ul>
  60. */
  61. TIMED_WAITING,
  62. /**
  63. * Thread state for a terminated thread.
  64. * The thread has completed execution.
  65. */
  66. TERMINATED;
  67. }

image.png

构造方法

  1. /**
  2. * 自动生成Thread-${nextThreadNum()}的线程名
  3. */
  4. public Thread() {
  5. init(null, null, "Thread-" + nextThreadNum(), 0);
  6. }
  7. public Thread(Runnable target) {
  8. init(null, target, "Thread-" + nextThreadNum(), 0);
  9. }
  10. /**
  11. * Creates a new Thread that inherits the given AccessControlContext.
  12. * This is not a public constructor.
  13. * 非public方法
  14. */
  15. Thread(Runnable target, AccessControlContext acc) {
  16. init(null, target, "Thread-" + nextThreadNum(), 0, acc, false);
  17. }
  18. /**
  19. *
  20. * @param group
  21. * the thread group. If {@code null} and there is a security
  22. * manager, the group is determined by {@linkplain
  23. * SecurityManager#getThreadGroup SecurityManager.getThreadGroup()}.
  24. * If there is not a security manager or {@code
  25. * SecurityManager.getThreadGroup()} returns {@code null}, the group
  26. * is set to the current thread's thread group.
  27. * 如果没有设置,则调用 securityManager.getThreadGroup
  28. * 没有的话用当前父线程的 Group
  29. *
  30. */
  31. public Thread(ThreadGroup group, Runnable target) {
  32. init(group, target, "Thread-" + nextThreadNum(), 0);
  33. }
  34. public Thread(String name) {
  35. init(null, null, name, 0);
  36. }
  37. public Thread(ThreadGroup group, String name) {
  38. init(group, null, name, 0);
  39. }
  40. public Thread(Runnable target, String name) {
  41. init(null, target, name, 0);
  42. }
  43. public Thread(ThreadGroup group, Runnable target, String name) {
  44. init(group, target, name, 0);
  45. }
  46. /**
  47. *
  48. * @param stackSize
  49. * the desired stack size for the new thread, or zero to indicate
  50. * that this parameter is to be ignored.
  51. * 这个参数将被忽略
  52. */
  53. public Thread(ThreadGroup group, Runnable target, String name,
  54. long stackSize) {
  55. init(group, target, name, stackSize);
  56. }

init()方法

所有的构造方法最终都是调用init()方法实现的。

  1. private void init(ThreadGroup g, Runnable target, String name,
  2. long stackSize, AccessControlContext acc,
  3. boolean inheritThreadLocals) {
  4. // 线程名必填
  5. if (name == null) {
  6. throw new NullPointerException("name cannot be null");
  7. }
  8. this.name = name;
  9. // 设置ThreadGroup
  10. Thread parent = currentThread();
  11. SecurityManager security = System.getSecurityManager();
  12. if (g == null) {
  13. /* Determine if it's an applet or not */
  14. /* If there is a security manager, ask the security manager
  15. what to do. */
  16. // 优先使用 securityManager
  17. if (security != null) {
  18. g = security.getThreadGroup();
  19. }
  20. /* If the security doesn't have a strong opinion of the matter
  21. use the parent thread group. */
  22. // 没有的话再使用父线程的TG
  23. if (g == null) {
  24. g = parent.getThreadGroup();
  25. }
  26. }
  27. /* checkAccess regardless of whether or not threadgroup is
  28. explicitly passed in. */
  29. g.checkAccess();
  30. /*
  31. * Do we have the required permissions?
  32. */
  33. if (security != null) {
  34. if (isCCLOverridden(getClass())) {
  35. security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
  36. }
  37. }
  38. g.addUnstarted();
  39. this.group = g;
  40. // 守护线程 使用 父线程的
  41. this.daemon = parent.isDaemon();
  42. // 优先级也使用父线程
  43. this.priority = parent.getPriority();
  44. if (security == null || isCCLOverridden(parent.getClass()))
  45. this.contextClassLoader = parent.getContextClassLoader();
  46. else
  47. this.contextClassLoader = parent.contextClassLoader;
  48. this.inheritedAccessControlContext =
  49. acc != null ? acc : AccessController.getContext();
  50. // runnable
  51. this.target = target;
  52. // 设置优先级
  53. setPriority(priority);
  54. // 取父线程的 inheritableThreadLocal
  55. if (inheritThreadLocals && parent.inheritableThreadLocals != null)
  56. this.inheritableThreadLocals =
  57. ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
  58. /* Stash the specified stack size in case the VM cares */
  59. this.stackSize = stackSize;
  60. /* Set thread ID 设置线程id */
  61. tid = nextThreadID();
  62. }

setPriority()方法

  1. public final void setPriority(int newPriority) {
  2. ThreadGroup g;
  3. checkAccess();
  4. if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
  5. throw new IllegalArgumentException();
  6. }
  7. if((g = getThreadGroup()) != null) {
  8. //线程的优先级不可能高于线程组的
  9. if (newPriority > g.getMaxPriority()) {
  10. newPriority = g.getMaxPriority();
  11. }
  12. setPriority0(priority = newPriority);
  13. }
  14. }

start()方法

  1. /**
  2. * Causes this thread to begin execution; the Java Virtual Machine
  3. * calls the <code>run</code> method of this thread.
  4. * <p>
  5. * The result is that two threads are running concurrently: the
  6. * current thread (which returns from the call to the
  7. * <code>start</code> method) and the other thread (which executes its
  8. * <code>run</code> method).
  9. * <p>
  10. *
  11. * It is never legal to start a thread more than once.
  12. * In particular, a thread may not be restarted once it has completed
  13. * execution.
  14. * 一个线程不能重复启用
  15. *
  16. * 如果线程已经start()会报错
  17. * @exception IllegalThreadStateException if the thread was already
  18. * started.
  19. * @see #run()
  20. * @see #stop()
  21. */
  22. public synchronized void start() {
  23. /**
  24. * This method is not invoked for the main method thread or "system"
  25. * group threads created/set up by the VM. Any new functionality added
  26. * to this method in the future may have to also be added to the VM.
  27. * 状态必须为 0
  28. * A zero status value corresponds to state "NEW".
  29. */
  30. if (threadStatus != 0)
  31. throw new IllegalThreadStateException();
  32. /* Notify the group that this thread is about to be started
  33. * so that it can be added to the group's list of threads
  34. * and the group's unstarted count can be decremented. */
  35. group.add(this);
  36. boolean started = false;
  37. try {
  38. // 调用 native方法
  39. start0();
  40. started = true;
  41. } finally {
  42. try {
  43. if (!started) {
  44. group.threadStartFailed(this);
  45. }
  46. } catch (Throwable ignore) {
  47. /* do nothing. If start0 threw a Throwable then
  48. it will be passed up the call stack */
  49. }
  50. }
  51. }
  52. private native void start0();

sleep()方法

  1. /**
  2. * Causes the currently executing thread to sleep (temporarily cease
  3. * execution) for the specified number of milliseconds, subject to
  4. * the precision and accuracy of system timers and schedulers. The thread
  5. * does not lose ownership of any monitors.
  6. *
  7. *
  8. * @throws InterruptedException
  9. * if any thread has interrupted the current thread. The
  10. * <i>interrupted status</i> of the current thread is
  11. * cleared when this exception is thrown.
  12. */
  13. public static native void sleep(long millis) throws InterruptedException;
  14. /**
  15. * Causes the currently executing thread to sleep (temporarily cease
  16. * execution) for the specified number of milliseconds plus the specified
  17. * number of nanoseconds, subject to the precision and accuracy of system
  18. * timers and schedulers. The thread does not lose ownership of any
  19. * monitors.
  20. *
  21. * 取决于系统计时器和调度程序的精度和准确性。
  22. * 线程不会失去任何监视器的所有权。
  23. *
  24. * @param millis
  25. * the length of time to sleep in milliseconds
  26. *
  27. * @param nanos
  28. * {@code 0-999999} additional nanoseconds to sleep
  29. *
  30. * @throws IllegalArgumentException
  31. * if the value of {@code millis} is negative, or the value of
  32. * {@code nanos} is not in the range {@code 0-999999}
  33. *
  34. * @throws InterruptedException
  35. * if any thread has interrupted the current thread. The
  36. * <i>interrupted status</i> of the current thread is
  37. * cleared when this exception is thrown.
  38. */
  39. public static void sleep(long millis, int nanos)
  40. throws InterruptedException {
  41. if (millis < 0) {
  42. throw new IllegalArgumentException("timeout value is negative");
  43. }
  44. if (nanos < 0 || nanos > 999999) {
  45. throw new IllegalArgumentException(
  46. "nanosecond timeout value out of range");
  47. }
  48. if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
  49. millis++;
  50. }
  51. sleep(millis);
  52. }

注:一般都是直接调用native

join()方法

  1. /**
  2. * Waits at most {@code millis} milliseconds for this thread to
  3. * die. A timeout of {@code 0} means to wait forever.
  4. * join()-> 会默认调用 join(0) 意味着wait 永久
  5. *
  6. * <p> This implementation uses a loop of {@code this.wait} calls
  7. * conditioned on {@code this.isAlive}. As a thread terminates the
  8. * {@code this.notifyAll} method is invoked. It is recommended that
  9. * applications not use {@code wait}, {@code notify}, or
  10. * {@code notifyAll} on {@code Thread} instances.
  11. * 实现方式是当前线程如果是isAlive的循环wait,
  12. *
  13. * @param millis
  14. * the time to wait in milliseconds
  15. *
  16. * @throws IllegalArgumentException
  17. * if the value of {@code millis} is negative
  18. *
  19. * @throws InterruptedException
  20. * if any thread has interrupted the current thread. The
  21. * <i>interrupted status</i> of the current thread is
  22. * cleared when this exception is thrown.
  23. */
  24. public final synchronized void join(long millis)
  25. throws InterruptedException {
  26. // 基础时间
  27. long base = System.currentTimeMillis();
  28. long now = 0;
  29. if (millis < 0) {
  30. throw new IllegalArgumentException("timeout value is negative");
  31. }
  32. if (millis == 0) {
  33. //当前线程一直存活,调用线程一直 wait();
  34. while (isAlive()) {
  35. wait(0);
  36. }
  37. } else {
  38. while (isAlive()) {
  39. long delay = millis - now;
  40. if (delay <= 0) {
  41. break;
  42. }
  43. wait(delay);
  44. now = System.currentTimeMillis() - base;
  45. }
  46. }
  47. }
  48. /**
  49. * Waits at most {@code millis} milliseconds plus
  50. * {@code nanos} nanoseconds for this thread to die.
  51. *
  52. * <p> This implementation uses a loop of {@code this.wait} calls
  53. * conditioned on {@code this.isAlive}. As a thread terminates the
  54. * {@code this.notifyAll} method is invoked. It is recommended that
  55. * applications not use {@code wait}, {@code notify}, or
  56. * {@code notifyAll} on {@code Thread} instances.
  57. *
  58. * @param millis
  59. * the time to wait in milliseconds
  60. *
  61. * @param nanos
  62. * {@code 0-999999} additional nanoseconds to wait
  63. *
  64. * @throws IllegalArgumentException
  65. * if the value of {@code millis} is negative, or the value
  66. * of {@code nanos} is not in the range {@code 0-999999}
  67. *
  68. * @throws InterruptedException
  69. * if any thread has interrupted the current thread. The
  70. * <i>interrupted status</i> of the current thread is
  71. * cleared when this exception is thrown.
  72. */
  73. public final synchronized void join(long millis, int nanos)
  74. throws InterruptedException {
  75. if (millis < 0) {
  76. throw new IllegalArgumentException("timeout value is negative");
  77. }
  78. if (nanos < 0 || nanos > 999999) {
  79. throw new IllegalArgumentException(
  80. "nanosecond timeout value out of range");
  81. }
  82. if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
  83. millis++;
  84. }
  85. join(millis);
  86. }
  87. /**
  88. * Waits for this thread to die.
  89. * 调用线程会等待该线程执行完毕,才运行
  90. * <p> An invocation of this method behaves in exactly the same
  91. * way as the invocation
  92. *
  93. *
  94. * @throws InterruptedException
  95. * if any thread has interrupted the current thread. The
  96. * <i>interrupted status</i> of the current thread is
  97. * cleared when this exception is thrown.
  98. */
  99. public final void join() throws InterruptedException {
  100. join(0);
  101. }

interrupt()方法

  1. public void interrupt() {
  2. if (this != Thread.currentThread())
  3. checkAccess();
  4. synchronized (blockerLock) {
  5. Interruptible b = blocker;
  6. if (b != null) {
  7. interrupt0(); // Just to set the interrupt flag
  8. b.interrupt(this);
  9. return;
  10. }
  11. }
  12. interrupt0();
  13. }
  • Just to set the interrupt flag

    suspend()方法

  • 挂起,线程如果是存活的,直到resumed才能继续进行

    stop()方法

    ```java @Deprecated public final void stop() { SecurityManager security = System.getSecurityManager(); if (security != null) {

    1. checkAccess();
    2. if (this != Thread.currentThread()) {
    3. security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION);
    4. }

    } // A zero status value corresponds to “NEW”, it can’t change to // not-NEW because we hold the lock. if (threadStatus != 0) {

    1. resume(); // Wake up thread if it was suspended; no-op otherwise

    }

    // The VM can handle all thread states stop0(new ThreadDeath()); }

  1. <a name="LCzMQ"></a>
  2. # 为什么stop()、resume()、suspend()被弃用
  3. <a name="SDH8J"></a>
  4. ## stop()被舍弃
  5. 1. 不安全,强制释放所有被锁定的监视器,某些共享数据可能处于不一致状态(转账一半结束了)
  6. 2. 使用者无感知
  7. <a name="lz5Yj"></a>
  8. ## resume()和suspend()被弃用
  9. 1. suspend()挂起了线程但是不会释放监视器上持有的锁,导致其他线程无法访问资源
  10. 2. 恢复目标线程的线程调用resume时,也试图加这个监视器锁,就会死锁
  11. 手写一个死锁现象
  12. ```java
  13. @Test
  14. public void testResumeAndSuspendLock() throws InterruptedException {
  15. Object o = new Object();
  16. Thread thread = new Thread(() -> {
  17. synchronized (o){
  18. while (true) {
  19. System.out.println("hello world");
  20. }
  21. }
  22. });
  23. thread.start();
  24. TimeUnit.SECONDS.sleep(1);
  25. Thread thread1 = new Thread(() -> {
  26. synchronized (o) {
  27. System.err.println("ee");
  28. thread.resume();
  29. }
  30. });
  31. thread1.start();
  32. thread.suspend();
  33. thread1.join();
  34. }