本来想看 ThreadLocal 的源码的,但发现其中最重要的 get/set 方法都是操纵的 Thread 类 中的 threadLocals 变量 (java.lang.ThreadLocal.ThreadLocalMap),索性先来看一下 Thread 的源码吧,可以留意一下其中与 ThreadLocal 相关的属性,这样下次阅读 ThreadLocal 的核心 API 时,就能够轻易理解其原理咯。不多 BB,直接上硬菜。

    实现多线程从本质上都是由 Thread 类 来完成的,其源码量很多,本次只看一些常见且重要的部分,源码和解析如下。

    1. public class Thread implements Runnable {
    2. /** 这里只看一些 常见的参数 */
    3. /** 线程名 */
    4. private volatile char name[];
    5. /** 优先级 */
    6. private int priority;
    7. /** 是否为守护线程 */
    8. private boolean daemon;
    9. /** 线程要执行的目标任务 */
    10. private Runnable target;
    11. /** 所属线程组 */
    12. private ThreadGroup group;
    13. /** 类加载器 */
    14. private ClassLoader contextClassLoader;
    15. /**
    16. * ThreadLocal 能为线程设置线程私有变量 就是通过下面这个threadLocals变量完成的,
    17. * ThreadLocal的get/set方法就是通过操作 各个线程的 threadLocals 变量实现的。
    18. * 1、线程A持有一个 ThreadLocalMap 变量;
    19. * 2、线程A调用一个类的 ThreadLocal变量 tlA 的 get/set方法;
    20. * 3、tlA(ThreadLocal)的 get/set方法 获取当前线程A,调用 线程A 的 ThreadLocalMap变量 的get/put方法;
    21. * 4、其它线程 调用 tlA(ThreadLocal)的 get/set方法 同理。
    22. */
    23. ThreadLocal.ThreadLocalMap threadLocals;
    24. ThreadLocal.ThreadLocalMap inheritableThreadLocals;
    25. /** 线程栈的大小 */
    26. private long stackSize;
    27. /**
    28. * Thread类定义了6个线程状态:New、Runnable、Blocked、Waiting、TimedWaiting、Terminated(终止)
    29. * 实际上还会把 Runnable 再细分为 就绪(未抢到时间片) 和 运行中(抢到时间片)
    30. */
    31. private volatile int threadStatus;
    32. /** 最小优先级 */
    33. public static final int MIN_PRIORITY = 1;
    34. /** 中等优先级 */
    35. public static final int NORM_PRIORITY = 5;
    36. /** 最大优先级 */
    37. public static final int MAX_PRIORITY = 10;
    38. /**
    39. * 内部枚举类,用来描述线程状态,状态值有:
    40. * NEW: 新建,还未调用start()方法;
    41. * RUNNABLE: 运行,在java多线程模型中,就绪和运行都是运行状态;
    42. * BLOCKED: 阻塞;
    43. * WAITING: 等待,需要其他的线程来唤醒;
    44. * TIMED_WAITING:超时等待,可以在指定的时间内自动醒来,如 sleep()方法;
    45. * TERMINATED: 终止,线程执行完毕。
    46. */
    47. public static final class State extends Enum {
    48. public static final State NEW;
    49. public static final State RUNNABLE;
    50. public static final State BLOCKED;
    51. public static final State WAITING;
    52. public static final State TIMED_WAITING;
    53. public static final State TERMINATED;
    54. private static final State VALUES[];
    55. static {
    56. NEW = new State("NEW", 0);
    57. RUNNABLE = new State("RUNNABLE", 1);
    58. BLOCKED = new State("BLOCKED", 2);
    59. WAITING = new State("WAITING", 3);
    60. TIMED_WAITING = new State("TIMED_WAITING", 4);
    61. TERMINATED = new State("TERMINATED", 5);
    62. VALUES = (new State[] { NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED });
    63. }
    64. private State(String s, int i) {
    65. super(s, i);
    66. }
    67. }
    68. /**
    69. * 一系列 构造方法 ------------------------------------------------------
    70. * 可以看出来,其中都调用了init()方法,这也是一个约定俗成的规矩, 即,如果要在 new 时进行一些初始化操作,
    71. * 那么请将初始化操作单独写在 init()方法中,然后在构造函数中调用该 init()方法
    72. */
    73. public Thread() {
    74. daemon = false;
    75. stillborn = false;
    76. threadLocals = null;
    77. inheritableThreadLocals = null;
    78. threadStatus = 0;
    79. blockerLock = new Object();
    80. init(null, null, (new StringBuilder()).append("Thread-").append(nextThreadNum()).toString(), 0L);
    81. }
    82. public Thread(Runnable runnable) {
    83. daemon = false;
    84. stillborn = false;
    85. threadLocals = null;
    86. inheritableThreadLocals = null;
    87. threadStatus = 0;
    88. blockerLock = new Object();
    89. init(null, runnable, (new StringBuilder()).append("Thread-").append(nextThreadNum()).toString(), 0L);
    90. }
    91. Thread(Runnable runnable, AccessControlContext accesscontrolcontext) {
    92. daemon = false;
    93. stillborn = false;
    94. threadLocals = null;
    95. inheritableThreadLocals = null;
    96. threadStatus = 0;
    97. blockerLock = new Object();
    98. init(null, runnable, (new StringBuilder()).append("Thread-").append(nextThreadNum()).toString(), 0L,
    99. accesscontrolcontext);
    100. }
    101. public Thread(ThreadGroup threadgroup, Runnable runnable) {
    102. daemon = false;
    103. stillborn = false;
    104. threadLocals = null;
    105. inheritableThreadLocals = null;
    106. threadStatus = 0;
    107. blockerLock = new Object();
    108. init(threadgroup, runnable, (new StringBuilder()).append("Thread-").append(nextThreadNum()).toString(), 0L);
    109. }
    110. public Thread(String s) {
    111. daemon = false;
    112. stillborn = false;
    113. threadLocals = null;
    114. inheritableThreadLocals = null;
    115. threadStatus = 0;
    116. blockerLock = new Object();
    117. init(null, null, s, 0L);
    118. }
    119. public Thread(ThreadGroup threadgroup, String s) {
    120. daemon = false;
    121. stillborn = false;
    122. threadLocals = null;
    123. inheritableThreadLocals = null;
    124. threadStatus = 0;
    125. blockerLock = new Object();
    126. init(threadgroup, null, s, 0L);
    127. }
    128. public Thread(Runnable runnable, String s) {
    129. daemon = false;
    130. stillborn = false;
    131. threadLocals = null;
    132. inheritableThreadLocals = null;
    133. threadStatus = 0;
    134. blockerLock = new Object();
    135. init(null, runnable, s, 0L);
    136. }
    137. public Thread(ThreadGroup threadgroup, Runnable runnable, String s) {
    138. daemon = false;
    139. stillborn = false;
    140. threadLocals = null;
    141. inheritableThreadLocals = null;
    142. threadStatus = 0;
    143. blockerLock = new Object();
    144. init(threadgroup, runnable, s, 0L);
    145. }
    146. public Thread(ThreadGroup threadgroup, Runnable runnable, String s, long l) {
    147. daemon = false;
    148. stillborn = false;
    149. threadLocals = null;
    150. inheritableThreadLocals = null;
    151. threadStatus = 0;
    152. blockerLock = new Object();
    153. init(threadgroup, runnable, s, l);
    154. }
    155. private void init(ThreadGroup threadgroup, Runnable runnable, String s, long l) {
    156. init(threadgroup, runnable, s, l, null);
    157. }
    158. /**
    159. * 初始化线程
    160. */
    161. private void init(ThreadGroup threadgroup, Runnable runnable, String name, long l,
    162. AccessControlContext accesscontrolcontext) {
    163. // 参数校验,线程name不能为null
    164. if (name == null)
    165. throw new NullPointerException("name cannot be null");
    166. this.name = name.toCharArray();
    167. // 当前线程就是该线程的父线程
    168. Thread parent = currentThread();
    169. SecurityManager securitymanager = System.getSecurityManager();
    170. if (threadgroup == null) {
    171. if (securitymanager != null)
    172. threadgroup = securitymanager.getThreadGroup();
    173. if (threadgroup == null)
    174. threadgroup = parent.getThreadGroup();
    175. }
    176. threadgroup.checkAccess();
    177. if (securitymanager != null && isCCLOverridden(getClass()))
    178. securitymanager.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
    179. threadgroup.addUnstarted();
    180. // 守护线程、优先级等设置为父线程的对应属性
    181. group = threadgroup;
    182. daemon = parent.isDaemon();
    183. priority = parent.getPriority();
    184. if (securitymanager == null || isCCLOverridden(parent.getClass()))
    185. contextClassLoader = parent.getContextClassLoader();
    186. else
    187. contextClassLoader = parent.contextClassLoader;
    188. inheritedAccessControlContext = accesscontrolcontext == null ? AccessController.getContext()
    189. : accesscontrolcontext;
    190. target = runnable;
    191. setPriority(priority);
    192. if (parent.inheritableThreadLocals != null)
    193. // 创建线程共享变量副本
    194. inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
    195. stackSize = l;
    196. // 分配线程id
    197. tid = nextThreadID();
    198. }
    199. public synchronized void start() {
    200. //假若当前线程初始化还未做好,不能start,0->NEW状态
    201. if (threadStatus != 0)
    202. throw new IllegalThreadStateException();
    203. //通知group该线程即将启动,group的未启动线程数量减1
    204. group.add(this);
    205. boolean started = false;
    206. try {
    207. // 调用native的start0()方法 启动线程,启动后执行run()方法
    208. start0();
    209. started = true;
    210. } finally {
    211. try {
    212. //启动不成功,group设置当前线程启动失败
    213. if (!started) {
    214. group.threadStartFailed(this);
    215. }
    216. } catch (Throwable ignore) {
    217. }
    218. }
    219. }
    220. private native void start0();
    221. public void run() {
    222. if (target != null)
    223. target.run();
    224. }
    225. /**
    226. * 请求终止线程。interrupt不会真正停止一个线程,它仅仅是给这个线程发了一个信号,
    227. * 告诉它要结束了,具体要中断还是继续运行,将由被通知的线程自己处理
    228. */
    229. public void interrupt() {
    230. if (this != Thread.currentThread())
    231. checkAccess();
    232. synchronized (blockerLock) {
    233. Interruptible b = blocker;
    234. if (b != null) {
    235. interrupt0();
    236. b.interrupt(this);
    237. return;
    238. }
    239. }
    240. interrupt0();
    241. }
    242. private native void interrupt0();
    243. /**
    244. * 线程main 调用了线程A的join方法,则 线程main 会被阻塞,直到线程A执行完毕
    245. */
    246. public final void join() throws InterruptedException {
    247. join(0);
    248. }
    249. /**
    250. * 实际上是利用 wait/notify机制 来实现的
    251. */
    252. public final synchronized void join(long millis) throws InterruptedException {
    253. long base = System.currentTimeMillis();
    254. long now = 0;
    255. if (millis < 0) {
    256. throw new IllegalArgumentException("timeout value is negative");
    257. }
    258. // millis 为 0,所以走这个分支
    259. if (millis == 0) {
    260. // 当前线程是否还在运行,还在运行 则main线程 进入等待状态,直到 A线程运行完毕,将其唤醒
    261. while (isAlive()) {
    262. wait(0);
    263. }
    264. } else {
    265. while (isAlive()) {
    266. long delay = millis - now;
    267. if (delay <= 0) {
    268. break;
    269. }
    270. wait(delay);
    271. now = System.currentTimeMillis() - base;
    272. }
    273. }
    274. }
    275. /**
    276. * 线程睡眠指定的时间,释放CPU资源,但不释放锁
    277. */
    278. public static native void sleep(long millis) throws InterruptedException;
    279. /**
    280. * 线程是否还在运行
    281. */
    282. public final native boolean isAlive();
    283. }

    之前一直对线程状态 及 状态切换的概念模糊不清,现在通过源码中对线程状态的定义,我们可以画张图来重新回顾一下,以使我们对其有更加深刻的理解。

    avatar