目录
  1. 1. Thread源码解析
    1. 1.1. 类定义
    2. 1.2. 主要变量
    3. 1.3. 构造方法
    4. 1.4. 内部类
      1. 1.4.1. 安全审核结果的缓存类Caches
      2. 1.4.2. 线程状态枚举类 State
    5. 1.5. 主要方法
      1. 1.5.1. Native方法
      2. 1.5.2. 线程初始化:init
      3. 1.5.3. 线程睡眠:sleep
      4. 1.5.4. 线程启动:start
      5. 1.5.5. 线程运行:run
      6. 1.5.6. 线程退出:exit
      7. 1.5.7. 线程中断:interrupt
      8. 1.5.8. 线程等待:join
      9. 1.5.9. 守护线程:daemon
      10. 1.5.10. 线程优先级:priority
      11. 1.5.11. 线程名称
      12. 1.5.12. 线程组
      13. 1.5.13. dumpstack
      14. 1.5.14. checkAccess
      15. 1.5.15. ContextClassLoader
      16. 1.5.16. 线程的堆栈转储
      17. 1.5.17. CCLOverridden验证
      18. 1.5.18. 线程id、线程状态
01-Thread源码解析

Thread源码解析

类定义

  线程是程序中的执行线程.Java虚拟机允许应用程序具有多个并发运行的执行线程.Java所有多线程的实现,均通过封装Thread类实现,所以深入Thread类,对深入理解java多线程很有必要
  每个线程都有一个优先级.具有较高优先级的线程优先于具有较低优先级的线程执行.每个线程可能会也可能不会被标记为守护程序.当在某个线程中运行的代码创建新的Thread对象时,新线程的优先级最初设置为与创建线程的优先级相等,并且当且仅当创建线程是守护程序时,该线程才是守护程序线程

主要变量

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// 线程名称
private volatile String name;
// 线程优先级
private int priority;
private Thread threadQ;
private long eetop;

/* 是否单步执行此线程. */
private boolean single_step;

/* 当前线程是否是守护程序线程 */
private boolean daemon = false;

/* JVM状态 */
private boolean stillborn = false;

/* 将会运行的逻辑代码 */
private Runnable target;

/* 该线程所在的组 */
private ThreadGroup group;

/* 此线程的上下文ClassLoader */
private ClassLoader contextClassLoader;

/* 该线程的继承的AccessControlContext */
private AccessControlContext inheritedAccessControlContext;

/* 用于自动编号匿名线程,当我们创建的线程没有命名,使用此值++的值作为线程名称 */
private static int threadInitNumber;
private static synchronized int nextThreadNum() {
return threadInitNumber++;
}

/* 与此线程绑定的ThreadLocal值.该映射由ThreadLocal类维护 */
ThreadLocal.ThreadLocalMap threadLocals = null;

/*
* 与此线程绑定的InheritableThreadLocal值.该映射由InheritableThreadLocal类维护
*/
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;


/*
* 此线程请求的堆栈大小
* 如果创建者未指定堆栈大小,则为0.由VM决定使用此编号执行任何操作.一些虚拟机将忽略它
*/
private long stackSize;

/*
* JVM私有状态在本地线程终止后仍然存在
*/
private long nativeParkEventPointer;

/*
* 线程id
*/
private long tid;

/* 用于生成线程ID */
private static long threadSeqNumber;
private static synchronized long nextThreadID() {
return ++threadSeqNumber;
}

/*
* Java线程状态的工具,线程的初始化状态为"尚未启动"
*/
private volatile int threadStatus = 0;

/**
* 提供给java.util.concurrent.locks.LockSupport.park的当前调用的参数
* 通过setBlocker设置值,通过getBlocker获取
*/
volatile Object parkBlocker;

/*
* 在可中断的I/O操作中阻塞该线程的对象(如果有).设置此线程的中断状态后,应调用阻塞程序的中断方法
*/
private volatile Interruptible blocker;
private final Object blockerLock = new Object();

/*
* 设置阻止字段;通过java.nio代码中的sun.misc.SharedSecrets调用
*/
void blockedOn(Interruptible b) {
synchronized (blockerLock) {
blocker = b;
}
}

/**
* 线程的最低优先级
*/
public final static int MIN_PRIORITY = 1;

/**
* 分配给线程的默认优先级
*/
public final static int NORM_PRIORITY = 5;

/**
* 线程的最大优先级。
*/
public final static int MAX_PRIORITY = 10;

构造方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
/**
* 分配一个新的线程对象
* 此构造函数具有与Thread(ThreadGroup,Runnable,String)相同的效果
* 其中name是新生成的名称.自动生成的名称为"Thread-"+n,其中n是整数
*/
public Thread() {
init(null, null, "Thread-" + nextThreadNum(), 0);
}

/**
* 分配一个新的线程对象.
* 此构造函数具有与Thread(ThreadGroup,Runnable,String)相同的效果
* 其中name是新生成的名称.自动生成的名称为"Thread-"+n,其中n是整数
*
* @param target 启动此线程时调用其run方法的对象.如果null,则此类 run方法不执行任何操作
*/
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}

/**
* 分配一个新的线程对象.
* 此构造函数具有与Thread(ThreadGroup,Runnable,String)相同的效果
* 其中name是新生成的名称.自动生成的名称为"Thread-"+n,其中n是整数
*
* @param group 当前线程的线程组.
如果为null}且存在安全管理器,则该组由SecurityManager.getThreadGroup()}确定.
如果没有安全管理器或SecurityManager.getThreadGroup()返回null,则将该组设置为当前线程的线程组
* @param target 在此线程启动时调用其target 的run方法的对象.如果null,则调用此线程的run方法
* @throws SecurityException 如果当前线程无法在指定的线程组中创建线程
*/
public Thread(ThreadGroup group, Runnable target) {
init(group, target, "Thread-" + nextThreadNum(), 0);
}

/**
* 分配一个新的线程对象.
* 此构造函数具有与Thread(ThreadGroup,Runnable,String)相同的效果
*
* @param name 新线程的名称
*/
public Thread(String name) {
init(null, null, name, 0);
}

/**
* 分配一个新的线程对象.
* 此构造函数具有与Thread(ThreadGroup,Runnable,String)相同的效果
*
* @param group 当前线程的线程组.
* @param name 新线程的名称
* @throws SecurityException
*/
public Thread(ThreadGroup group, String name) {
init(group, null, name, 0);
}

/**
* 分配一个新的线程对象.
* 此构造函数具有与Thread(ThreadGroup,Runnable,String)相同的效果
* @param target 启动此线程时调用其run方法的对象.如果null,则此类 run方法不执行任何操作
* @param name 新线程的名称
*/
public Thread(Runnable target, String name) {
init(null, target, name, 0);
}

/**
* 分配一个新的Thread对象,使其具有target作为其运行对象,具有指定的name作为其名称,并且属于group所引用的线程组
*
* 如果有安全管理器,则用ThreadGroup作为参数调用其checkAccess(ThreadGroup)方法
*
* 另外当子类的构造函数直接或间接调用覆盖了getContextClassLoader或setContextClassLoader的子类时,其checkPermission方法是通过RuntimePermission("enableContextClassLoaderOverride")}权限调用的方法
*
* 新创建的线程的优先级设置为等于创建它的线程的优先级,即当前正在运行的线程.方法setPriority可用于将优先级更改为新值
*
* 新创建的线程最初标记为守护进程线程,如果并且仅当创建它的线程当前标记为守护进程线程时.方法setDaemon可用于更改线程是否是守护进程
*
* @param group
* @param target
* @param name
* @throws SecurityException
*/
public Thread(ThreadGroup group, Runnable target, String name) {
init(group, target, name, 0);
}

/**
* 分配一个新的Thread对象
* 指定target作为其运行对象,指定的name作为其名称,指定group为所引用的线程组,指定的堆栈大小
*
* 此构造函数与Thread(ThreadGroup,Runnable,String)相同,但允许指定线程堆栈大小这一事实除外.堆栈大小是虚拟机要为此线程的堆栈分配的地址空间的大致字节数.stackSize
*
* 由于此构造函数的行为依赖于平台,因此在使用它时应格外小心.从一个JRE实现到另一个JRE实现,执行给定计算所需的线程堆栈大小可能会有所不同.鉴于这种变化,可能需要仔细调整堆栈大小参数,并且可能需要针对运行应用程序的每个JRE实现重复进行该调整
* @param group
* @param target
* @param name
* @param stackSize
* @throws SecurityException
*/
public Thread(ThreadGroup group, Runnable target, String name, long stackSize) {
init(group, target, name, stackSize);
}

内部类

安全审核结果的缓存类Caches

1
2
3
4
5
6
7
8
9
10
/* 请用ConcurrentReferenceHashMap替换 */
private static class Caches {
/** 子类安全审核结果的缓存 */
static final ConcurrentMap<WeakClassKey,Boolean> subclassAudits =
new ConcurrentHashMap<>();

/** 排队等待对已审计子类的弱引用 */
static final ReferenceQueue<Class<?>> subclassAuditsQueue =
new ReferenceQueue<>();
}

线程状态枚举类 State

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* 线程状态.线程可以处于以下状态之一:
* 新建 -- 线程尚未启动
* 可执行 -- 在Java虚拟机中执行的线程处于这种状态
* 阻塞 -- 等待监视器锁定而被阻塞的线程处于此状态
* 无限等待 -- 无限期地等待另一个线程执行特定操作的线程处于此状态
* 定时等待 -- 正在等待另一个线程执行操作的线程最多达到指定的等待时间,该线程处于此状态
* 终止 -- 退出的线程处于此状态
*
* 在给定的时间点,线程只能处于一种状态.这些状态是虚拟机状态,不反映任何操作系统线程状态
*/
public enum State {
NEW,

RUNNABLE,

BLOCKED,

WAITING,

TIMED_WAITING,

TERMINATED;
}

主要方法

Native方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/**
* 返回对当前正在执行的线程对象
*/
public static native Thread currentThread();

/**
* 线程让步:当前线程愿意放弃当前使用的CPU.使当前线程由运行状态转为可执行状态
*/
public static native void yield();

/**
* 线程睡眠:根据系统计时器和调度程序的精度和准确性,使当前正在执行的线程进入休眠状态(暂时停止执行)达指定的毫秒数.该线程不会失去任何监视器的所有权
*
* @param millis 睡眠时间(以毫秒为单位)
* @throws IllegalArgumentException 如果millis的值为负
* @throws InterruptedException 如果有任何线程中断了当前线程.抛出此异常时,将清除当前线程的中断状态
*/
public static native void sleep(long millis) throws InterruptedException;

// 线程启动
private native void start0();

// 线程中断
private native boolean isInterrupted(boolean ClearInterrupted);

// 返回此线程是否仍然存活.如果线程已经启动但尚未死亡,则该线程是活动的
public final native boolean isAlive();

// 当且仅当当前线程在指定对象上持有监视器锁定时返回true
public static native boolean holdsLock(Object obj);

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);

线程初始化:init

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
/**
* 使用当前的AccessControlContext初始化线程
*/
private void init(ThreadGroup g, Runnable target, String name, long stackSize) {
init(g, target, name, stackSize, null, true);
}

/**
* 初始化线程
*
* @param g 线程组
* @param target 实现具体run()方法的内容
* @param name 初始化线程的名称
* @param stackSize 创建线程的所需堆栈大小,或者为0表示要忽略此参数
* @param acc 要继承的AccessControlContext;如果为null,则为AccessController.getContext()
* @param inheritThreadLocals 如果为 true,则从构造线程继承可继承线程局部变量的初始值
*/
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;

Thread parent = currentThread();
SecurityManager security = System.getSecurityManager();
/* 确定是否没有挂靠线程组 */
if (g == null) {
/* 如果有安全管理,则挂在安全的线程组中 */
if (security != null) {
g = security.getThreadGroup();
}

/* 如果没有安全管理,则挂在父线程组中 */
if (g == null) {
g = parent.getThreadGroup();
}
}

/* 不管是否显式传递线程组,都应使用checkAccess */
g.checkAccess();

/*
* 我们具有所需的权限吗
*/
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);

/* 存放指定的堆栈大小,以防VM关心 */
this.stackSize = stackSize;

/* 设置当前线程id */
tid = nextThreadID();
}

线程睡眠:sleep

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* 线程睡眠:根据系统计时器和调度程序的精度和准确性,使当前正在执行的线程进入休眠状态(暂时停止执行)达指定的毫秒数加上指定的纳秒数.该线程不会失去任何监视器的所有权
*
* @param millis 睡眠时间(以毫秒为单位)
* @param nanos 额外的纳秒睡眠时间(0-999999)
* @throws IllegalArgumentException
* @throws InterruptedException
*/
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");
}
// 在millis为0而nanos有值的情况下,millis++;或nanos>=500000时millis++
if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
millis++;
}

sleep(millis);
}

线程启动:start

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
/**
* 使该线程开始执行;Java虚拟机将调用此线程的run方法
*
* 结果是两个线程正在同时运行:当前线程(从调用返回到start方法)和另一个线程(执行其run方法)
*
* 一次启动一个线程永远是不合法的.特别是,线程一旦完成执行就可能不会重新启动
*
* @exception IllegalThreadStateException 如果线程已经启动
*/
public synchronized void start() {
/**
* 零值对应于状态新建,此处主要判断当前线程只能启动一次,不能被重复启动
*/
if (threadStatus != 0)
throw new IllegalThreadStateException();

/* 通知组该线程将要启动,以便可以将其添加到组的线程列表中,并且可以减少该组的未启动计数 */
group.add(this);

boolean started = false;
try {
start0();
started = true;
} finally {
try {
// 如果线程启动失败,从线程组里面移除该线程
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
/* 什么也不做.如果start0抛出了Throwable,则它将被向上传递到调用堆栈 */
}
}
}

线程运行:run

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* 如果该线程是使用单独的Runnable运行对象构造的,则调用该Runnable对象的run方法;否则此方法不执行任何操作并返回
* Thread的子类应重写此方法
* @see #start()
* @see #stop()
* @see #Thread(ThreadGroup, Runnable, String)
*/
@Override
public void run() {
if (target != null) {
target.run();
}
}

线程退出:exit

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
/**
* 系统调用此方法,使线程有机会在线程实际退出之前进行清理
*/
private void exit() {
if (group != null) {
group.threadTerminated(this);
group = null;
}
/* 积极清空所有参考字段 */
target = null;
/* 加快释放其中一些资源 */
threadLocals = null;
inheritableThreadLocals = null;
inheritedAccessControlContext = null;
blocker = null;
uncaughtExceptionHandler = null;
}

线程中断:interrupt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/**
* 中断此线程
*
* 除非当前线程中断自身(始终允许),否则将调用此线程的checkAccess()方法,这可能会导致引发SecurityException
*
* 如果此线程在Object.wait()方法的调用中被阻塞,则Object类或JOIN()、sleep(Long,int)的调用方法,则将清除其中断状态,并接收InterruptedException
*/
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();
}

/**
* 返回当前线程是否已被中断.通过此方法可以清除线程的中断状态.
* 即如果要连续调用此方法两次,则第二次调用将返回false(除非当前线程在第一次调用清除其中断状态之后且在第二次调用检查其状态之前再次中断).
*/
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}

/**
* 返回此线程是否已被中断
* 线程的中断状态不受此方法的影响
*/
public boolean isInterrupted() {
return isInterrupted(false);
}

线程等待:join

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
/**
* 等待最多millis毫秒以使该线程消失.超时意味着永远等待
*/
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");
}
// 如果millis == 0 线程将一直等待下去
if (millis == 0) {
while (isAlive()) { // isAlive获取线程状态,无线等待直到previousThread线程结束
wait(0); // 调用Object中的wait方法实现线程的阻塞
}
} else {
// 指定了millis,等待指定时间以后,会break当前线程
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}

/**
* 等待最多毫秒(millis)加纳秒(nanos)的时间来使该线程死亡
*/
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);
}

public final void join() throws InterruptedException {
join(0);
}

守护线程:daemon

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
* 将此线程标记为守护进程.当运行的唯一线程是所有守护进程线程时,Java虚拟机将退出
* 必须在线程启动之前调用此方法
*/
public final void setDaemon(boolean on) {
checkAccess();
if (isAlive()) {
throw new IllegalThreadStateException();
}
daemon = on;
}

/**
* 返回当前线程是否是守护程序线程
*/
public final boolean isDaemon() {
return daemon;
}

线程优先级:priority

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/**
* 更改此线程的优先级
*/
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);
}
}

/**
* 返回此线程的优先级
*/
public final int getPriority() {
return priority;
}

线程名称

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* 将此线程的名称更改为name
*/
public final synchronized void setName(String name) {
checkAccess();
if (name == null) {
throw new NullPointerException("name cannot be null");
}

this.name = name;
if (threadStatus != 0) {
setNativeName(name);
}
}

/**
* 返回线程名称
*/
public final String getName() {
return name;
}

线程组

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
* 返回该线程所属的线程组.如果该线程死亡,则此方法返回null
*/
public final ThreadGroup getThreadGroup() {
return group;
}

/**
* 返回当前线程的ThreadGroup线程组及其子组中活动线程的数量的估计值
* 递归地迭代当前线程的线程组中的所有子组.主要用于调试和监视目的
*/
public static int activeCount() {
return currentThread().getThreadGroup().activeCount();
}

/**
* 将在当前线程的线程组中的每个活动线程及其子组复制到指定的阵列中
*/
public static int enumerate(Thread tarray[]) {
return currentThread().getThreadGroup().enumerate(tarray);
}

dumpstack

1
2
3
4
5
6
/**
* 将当前线程的堆栈跟踪记录打印到标准错误流.此方法仅用于调试
*/
public static void dumpStack() {
new Exception("Stack trace").printStackTrace();
}

checkAccess

1
2
3
4
5
6
7
8
9
10
11
/**
* 确定当前正在运行的线程是否有权修改此线程
*
* 如果有安全管理器,则以该线程作为参数调用其checkAccess方法.这可能导致抛出SecurityException
*/
public final void checkAccess() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkAccess(this);
}
}

ContextClassLoader

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
/**
* 返回此线程的上下文ClassLoader
*/
@CallerSensitive
public ClassLoader getContextClassLoader() {
if (contextClassLoader == null)
return null;
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
ClassLoader.checkClassLoaderPermission(contextClassLoader,
Reflection.getCallerClass());
}
return contextClassLoader;
}

/**
* 设置此线程的上下文ClassLoader
*/
public void setContextClassLoader(ClassLoader cl) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new RuntimePermission("setContextClassLoader"));
}
contextClassLoader = cl;
}

线程的堆栈转储

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
private static final StackTraceElement[] EMPTY_STACK_TRACE = new StackTraceElement[0];

/**
* 返回表示该线程的堆栈转储的堆栈跟踪元素的数组
* 如果此线程尚未启动,则此方法将返回零长度数组
* 如果返回的数组长度不为零,则数组的第一个元素表示栈顶,这是序列中最近的方法调用.数组的最后一个元素代表堆栈的底部,这是序列中最近的方法调用
*/
public StackTraceElement[] getStackTrace() {
if (this != Thread.currentThread()) {
// 检查getStackTrace权限
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkPermission(
SecurityConstants.GET_STACK_TRACE_PERMISSION);
}
// 优化,因此我们不会针对尚未启动或已终止的线程调用vm
if (!isAlive()) {
return EMPTY_STACK_TRACE;
}
StackTraceElement[][] stackTraceArray = dumpThreads(new Thread[] {this});
StackTraceElement[] stackTrace = stackTraceArray[0];
// 在上一个isAlive调用期间处于活动状态的线程可能已终止,因此没有堆栈跟踪
if (stackTrace == null) {
stackTrace = EMPTY_STACK_TRACE;
}
return stackTrace;
} else {
// 当前线程不需要JVM帮助
return (new Exception()).getStackTrace();
}
}

/**
* 返回所有活动线程的堆栈跟踪的映射
* 映射键是线程,每个映射值是一个StackTraceElement数组,该数组代表相应Thread的堆栈转储.返回的堆栈跟踪采用为getStackTrace方法指定的格式
*/
public static Map<Thread, StackTraceElement[]> getAllStackTraces() {
// 检查getStackTrace权限
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkPermission(
SecurityConstants.GET_STACK_TRACE_PERMISSION);
security.checkPermission(
SecurityConstants.MODIFY_THREADGROUP_PERMISSION);
}

// 获取所有线程列表的快照
Thread[] threads = getThreads();
StackTraceElement[][] traces = dumpThreads(threads);
Map<Thread, StackTraceElement[]> m = new HashMap<>(threads.length);
for (int i = 0; i < threads.length; i++) {
StackTraceElement[] stackTrace = traces[i];
if (stackTrace != null) {
m.put(threads[i], stackTrace);
}
// 否则终止了,所以我们不把它放在map上
}
return m;
}

/**
* 从指定映射中移除已排队在指定参考队列上的所有键
*/
static void processQueue(ReferenceQueue<Class<?>> queue, ConcurrentMap<? extends WeakReference<Class<?>>, ?> map) {
Reference<? extends Class<?>> ref;
while((ref = queue.poll()) != null) {
map.remove(ref);
}
}

CCLOverridden验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
private static final RuntimePermission SUBCLASS_IMPLEMENTATION_PERMISSION = new RuntimePermission("enableContextClassLoaderOverride");

/**
* 验证是否可以在不违反安全约束的情况下构造此(可能是子类)实例:子类不得覆盖对安全性敏感的非最终方法,否则将检查"enableContextClassLoaderOverride"RuntimePermission
*/
private static boolean isCCLOverridden(Class<?> cl) {
if (cl == Thread.class)
return false;

processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits);
WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue);
Boolean result = Caches.subclassAudits.get(key);
if (result == null) {
result = Boolean.valueOf(auditSubclass(cl));
Caches.subclassAudits.putIfAbsent(key, result);
}

return result.booleanValue();
}

线程id、线程状态

1
2
3
4
5
6
7
8
9
10
// 返回线程id
public long getId() {
return tid;
}

// 返回线程状态
public State getState() {
// get current thread state
return sun.misc.VM.toThreadState(threadStatus);
}
文章作者: Eric Liang
文章链接: https://ericql.github.io/2019/11/12/02-Java%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/02-%E5%B9%B6%E5%8F%91%E5%8C%85/01-Thread%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Eric Liang
打赏
  • 微信
  • 支付宝