1 线程简介
首先我们要清楚的是,任何程序想要实现线程都需要内核线程的支持,至少要有一个,不然程序无法执行。用户线程和内核线程的比例(M:N)体现了线程的不同实现方式。而对于高版本的Java(1.3及以后版本),一个Java的Thread就对应一个操作系统的线程。
/**
* 可以创建多个线程
* <p>
* 每个线程都有优先级。
* 指优先级越高,越有可能先执行。因为高优先级的拥有更多资源,更容易抢到CPU资源而已。
* 线程优先级有继承效果,比如main线程创建了线程A,则线程A初始优先级继承main的优先级,但是还可以修改为其他优先级。
* <p>
* 线程分为用户线程和守护线程。
* 用户线程执行完之后,不管守护线程有没有执行完,jvm都会关闭
* 守护线程A创建的线程B也是守护线程,但是守护线程B在未执行之前可以设置为非守护线程
* setDemon()方法当线程开始之后就不可以设置了
* if (isAlive()) {
* throw new IllegalThreadStateException();
* }
* <p>
* 创建线程 1 :继承Thread类
* 创建线程 2 :实现Runnable接口
* 创建线程 1 :实现Callable<>接口 通过FuntureTask(Callable<> caller) 实现,
* 本质上还是第二种方式,因为FutureTask实现了 Runnable接口
* <p>
* The following code would then create a thread and start it running:
* <blockquote><pre>
* PrimeRun p = new PrimeRun(143);
* new Thread(p).start();
* </pre></blockquote>
* <p>
* 每个线程的名称都是不同的,如果存在相同的线程名称,会将设置相同名字的后一个线程重新生成名称
* <p>
*/
public class Thread implements Runnable {
/**
* 初始化本地方法,(native方法) 当执行时不需要再去类库加载,提升性能 静态方法,类级别的
* 可以理解成为本类的本地方法 提前注册进来 提升执行时的性能
* 都是静态的,类装载时执行
*/
private static native void registerNatives();
static {
registerNatives();
}
}
2 线程上下文
CPU在一个时刻只能运行一个线程,当在运行一个线程的过程中转去运行另外一个线程,这个叫做线程上下文切换(对于进程也是类似)。
由于可能当前线程的任务并没有执行完毕,所以在切换时需要保存线程的运行状态,以便下次重新切换回来时能够继续切换之前的状态运行。举个栗子:线程A正在读取文件,当读到一半时需要暂停线程A,转去执行线程B,当再次切换回来执行线程A的时候,我们不希望线程A又从文件的开头来读取。因此需要记录线程A的运行状态和执行位置等,那么会记录哪些数据呢?因为下次恢复时需要知道在这之前当前线程已经执行到哪条指令了,所以需要记录程序计数器的值,另外比如说线程正在进行某个计算的时候被挂起了,那么下次继续执行的时候需要知道之前挂起时变量的值时多少,因此需要记录CPU寄存器的状态。所以一般来说,线程上下文切换过程中会记录程序计数器、CPU寄存器状态等数据。
对于线程的上下文切换实际上就是 存储和恢复CPU状态的过程,它使得线程执行能够从中断点恢复执行。
虽然多线程可以使得任务执行的效率得到提升,但是由于在线程切换时同样会带来一定的开销代价,并且多个线程会导致系统资源占用的增加,所以在进行多线程编程时要注意这些因素。
3 线程参数
private volatile String name; //线程名称
private int priority; //线程优先级
private Thread threadQ; //暂时不知道是干什么的,请教各位大佬 (感觉和JVM有关)
private long eetop; //JVM中的JavaThread指针
private boolean single_step;//字面意思 是否单步执行 请教各位大佬具体细节(感觉和JVM有关)
private boolean daemon = false; //是否是守护线程,默认false
private boolean stillborn = false; //字面意思 夭折 请教各位大佬具体细节(感觉和JVM state有关)
private Runnable target; //指定运行其中的Runnable,一般都需要指定,不指定的线程没有意义,或者可以通过创建Thread的子类并重新run方法。
private ThreadGroup group; //指定当前线程的线程组,未指定时线程组为创建该线程所属的线程组。线程组可以用来管理一组线程,通过activeCount() 来查看活动线程的数量。感觉除了这个没有什么大的用处。如果有其他用处或理解欢迎留言
private ClassLoader contextClassLoader; //线程用的上下文类加载器,该上下文类加载器可供线程加载类和资源
private AccessControlContext inheritedAccessControlContext; //继承的访问系统资源的上下文(本线程的)
private static int threadInitNumber;//计数变量,用在nextThreadNum方法中为匿名线程生成名称
ThreadLocal.ThreadLocalMap threadLocals = null; //线程局部变量
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null; //可继承的线程局部变量 比如一些 logId uid token 什么项目中共用的一些参数及标准 如果{true},则从构造线程 继承(inheritableThreadLocals) 的初始值 public的构造器 此参数均为true
private long stackSize;// 新线程预期所需的堆栈大小,或者零表示该参数将被忽略。与平台相关,不建议使用该属性。
private long nativeParkEventPointer;//native线程终止后,保持虚拟机私有状态
private long tid;//线程id
private static long threadSeqNumber;//为了生成线程ID
private volatile int threadStatus = 0; // java线程状态,已初始化,0代表'not yet started'
volatile Object parkBlocker; //LockSupport.park是提供给当前调用的参数,由 LockSupport.setBlocker 设置,通过LockSupport.getBlocker访问
private volatile Interruptible blocker;//此线程在 可中断I/O操作中 被阻塞的对象(如果有)。设置此线程的中断状态后,应调用 该对象的中断方法。
private final Object blockerLock = new Object();
4 线程优先级
1.java线程是通过映射到系统的原生线程上来实现的,所以线程的调度最终还是取决于操作系统,操作系统的优先级与java的优先级并不一一对应,如果操作系统的优先级级数大于java的优先级级数(10级)还好,但是如果小于得的话就不行了,这样会导致不同优先级的线程的优先级是一样的。
2.优先级可能会被系统自动改变,比如windows系统中就存在一个优先级推进器,大致功能就是如果一个线程执行的次数过多的话,可能会越过优先级为他分配执行时间
3.线程的调度最终还是取决于操作系统中的线程规划器。其实,即使设置了线程的优先级,一样无法确保这个线程一定先执行,因为它有很大的随机性。它并无法控制执行哪个线程,因为线程的执行,是抢占资源后才能执行的操作,而抢点资源时,最多是给于线程优先级较高的线程一点机会而已,能不能抓住可是不一定的。
说到底就一句话:线程优化级较高的线程不一定先执行。
5 线程状态
线程内部枚举有6种状态:NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING、TERMINATED
NEW:新生;尚未启动的线程的线程状态
RUNNABLE:可运行; 可运行线程的线程状态。
处于可运行状态的线程正在Java虚拟机中执行,但可能需要等待其他资源调度,如CPU。
BLOCKED:阻塞;处于阻塞状态的线程正在等待锁。BLOCKED 状态可以视作是一种特殊的 WAITING,特指等待锁。
BLOCKED 源码注释:
1.一个处于 blocked 状态的线程正在等待一个监视器锁以进入一个同步的块或方法。
A thread in the blocked state is waiting for a monitor lock to enter a synchronized block/method or
2.或在其调用 Object.wait 方法之后,以再次进入一个同步的块或方法。
reenter a synchronized block/method after calling Object.wait
第一句:本线程在等待其他线程释放锁,获得锁之后才能执行后面锁住的代码块或者方法。
第二句:本线程持有锁,内部调用 Object.wait 方法进入阻塞状态,这时会释放锁,等待其他线程 Object.notify方法将本线程唤醒,唤醒后需要重新获取到锁才能继续执行后面的代码块。可以看出以下几点:
1.必须持有该锁才能调用该锁的 wait 方法,这是第一次 enter。
2.调用 wait 之后线程会释放该锁,并进入该锁的等待队列(wait set)中,状态变为WAITING。
3.当收到其它线程对该锁的 notify 或 notifyAll 通知之后,等待线程并不能立即恢复执行,因为停止的地方是在同步块内,而锁已经释放了,所以它要重新获取锁才能再次执行后续的同步块reenter。这是第二次 enter,所以叫 reenter。
4.但是该线程还是要与其它线程去竞争锁,这一过程跟 enter 的过程一样,因此也会因为锁已经被其它线程据有而导致 BLOCKED。
WAITING:等待;一个正在无限期等待其他线程执行完成处于这一状态,他和BLOCKED区别在于需不需要等待锁。
TIMED_WAITING:持续时间等待,有限期的等待;
TERMINATED:结束。
6 线程方法
Thread Thread.currentThread() //获得当前线程的引用。
boolean isAlive() //测试线程是否处于活动状态。
void setDaemon(boolean on) //设置线程是否为守护线程
boolean isDaemon() //测试线程是否为守护线程。
void checkAccess() //判断当前运行的线程是否有权修改该线程。
int Thread.activeCount()//当前线程所在线程组中活动线程的数目。
StackTraceElement[] getStackTrace() //获取堆栈数组。
void dumpStack() //打印堆栈。
int enumerate(Thread[] tarray) //将当前线程的线程组及其子组中的每一个活动线程复制到指定的数组中。
Map<Thread,StackTraceElement[]> getAllStackTraces() //返回所有活动线程的堆栈跟踪的一个映射。
boolean holdsLock(Object obj) //当且仅当当前线程在指定的对象上保持监视器锁时,才返回 true。
void setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh) //设置由于未捕获到异常导致线程终止时所调用的默认处理程序。
Thread.UncaughtExceptionHandler getDefaultUncaughtExceptionHandler() //返回线程由于未捕获到异常而突然终止时调用的默认处理程序。
Thread.UncaughtExceptionHandler getUncaughtExceptionHandler() //返回该线程由于未捕获到异常而突然终止时调用的处理程序。
void interrupt() //中断线程。
boolean isInterrupted()//测试线程是否已经中断。
boolean interrupted() //测试当前线程是否已经中断。
void sleep(long millis) //休眠指定时间
void sleep(long millis, int nanos) //休眠指定时间
void yield() //释放cpu资源进入就绪状态重新争抢资源。意义不太大
void join() //等待该线程终止。(内部也依赖的wait方法)
void join(long millis) //等待该线程终止的时间最长为 millis 毫秒。
void join(long millis, int nanos) //等待该线程终止的时间最长为 millis 毫秒 + nanos 纳秒。
void setContextClassLoader(ClassLoader cl) //设置该线程的上下文 ClassLoader。
void start()//使该线程开始执行;Java 虚拟机调用该线程的 run 方法。
void run() //线程启动后执行的方法。
比较重要的方法
/**
* 使线程进入就绪状态,等竞争到CPU资源后执行下面的run()方法
*
* @throws IllegalThreadStateException 线程启动后再次调用会报错
*/
public synchronized void start() {
/**
* VM创建的线程或者系统线程组创建的线程 不是通过此方法创建的. 该方法逻辑可能会变化.
*/
//0是就绪状态 已经是就绪状态,再调用此方法后就会报错
if (threadStatus != 0) throw new IllegalThreadStateException();
//通知线程组 该线程将要启动
group.add(this);
boolean started = false;
try {
//native方法,通过虚拟机启动线程
start0();
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
//什么也不做。防止覆盖start0抛出的异常,让该异常向上传递
}
}
}
/**
* 争抢到CPU资源 线程真正执行的方法
*/
@Override
public void run() {
if (target != null) {
target.run();
}
}
/**
* 中断此线程.
*/
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();
}
/**
* 测试当前线程是否已被中断。并且清除线程的 中断状态
* 当前线程已被中断 返回true 并且清除线程的 中断状态(置为false)
*/
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
/**
* 测试当前线程是否已被中断。 和上面方法差别是该方法 不清除线程的中断状态
* 当前线程已被中断 返回true
*/
public boolean isInterrupted() {
return isInterrupted(false);
}
/**
* private 测试当前线程是否已被中断 根据参数看是否需要清楚中断状态
*/
private native boolean isInterrupted(boolean ClearInterrupted);
Thread.sleep(1000); 与 Thread.currentThread().sleep(1000); 等价,都是在何处调用,就会使得当前的线程进入休眠状态, main线程调用threadB.sleep(1000)与调用Thread.sleep(1000)一样,都是使main线程休眠1000毫秒,而不是使threadB休眠。
sleep方法不会释放锁。因为不强制需要锁
sleep()支持中断,因此当检测到中断信号(isInterrupt=1)时,会抛出InterruptedException 异常,因此在cache块中可以对如果发生中断进行某些操作。通过isInterrupted()可以发现:在抛出异常的时候,还让异常状态重新置为了false(isInterrupt=0)。
需要注意:由于不允许不同的线程之间的异常溢出,因此在run方法中就必须对此处抛出的InterruptedException异常进行处理,因此上述示例代码,直接对异常进行了捕捉。若是在其他的普通方法中,除非是线程需要退出,否则都不应当直接将异常生吞。此时可以选择:1.不捕捉 InterruptedException,将它传播给调用者;2.捕捉InterruptedException执行必要的清理操作,重新向上抛出InterruptedException异常;3.捕捉 InterruptedException 后重新恢复中断状态。
6 其他
创建线程:1Runnable接口,2.继承Thread类,实际上也是实现Runnable接口,3.Callable/Future 4.线程池
实际应用:
1、后台任务,例如:文件跑批,文件导出,定时百万用户推送消息;
2、异步处理,例如:多线程异步处理,提高程序响应;记录日志;Tomcat内部分发请求;BIO模型优化:
Socket socket = socket.accept();//阻塞,连接阻塞
New Thread(new Handler(socket)).start();//解决了r/w阻塞问题
3、分布式计算
Thread类源码
/**
* 可以创建多个线程
* <p>
* 每个线程都有优先级。
* 指优先级越高,越有可能先执行。因为高优先级的拥有更多资源,更容易抢到CPU资源而已。
* 线程优先级有继承效果,比如main线程创建了线程A,则线程A初始优先级继承main的优先级,但是还可以修改为其他优先级。
* <p>
* 线程分为用户线程和守护线程。
* 用户线程执行完之后,不管守护线程有没有执行完,jvm都会关闭
* 守护线程A创建的线程B也是守护线程,但是守护线程B在未执行之前可以设置为非守护线程
* setDemon()方法当线程开始之后就不可以设置了
* if (isAlive()) {
* throw new IllegalThreadStateException();
* }
* <p>
* 创建线程 1 //继承Thread类
* 创建线程 2 //实现Runnable接口
* 创建线程 1 //实现Callable<>接口 通过FuntureTask(Callable<> caller) 实现,
* 本质上还是第二种方式,因为FutureTask实现了 Runnable接口
* <p>
* The following code would then create a thread and start it running:
* <blockquote><pre>
* PrimeRun p = new PrimeRun(143);
* new Thread(p).start();
* </pre></blockquote>
* <p>
* 每个线程的名称都是不同的,如果存在相同的线程名称,会将设置相同名字的后一个线程重新生成名称
* <p>
*/
public class Thread implements Runnable {
/**
* 初始化本地方法,(native方法) 当执行时不需要再去类库加载,提升性能 静态方法,类级别的
* 可以理解成为本类的本地方法 提前注册进来 提升执行时的性能
* 都是静态的,类装载时执行
*/
private static native void registerNatives();
static {
registerNatives();
}
private volatile String name; //线程名称
private int priority; //线程优先级
private Thread threadQ; //暂时不知道是干什么的,请教各位大佬 (感觉和JVM有关)
private long eetop; //JVM中的JavaThread指针
private boolean single_step;//字面意思 是否单步执行 请教各位大佬具体细节(感觉和JVM有关)
private boolean daemon = false; //是否是守护线程,默认false
private boolean stillborn = false; //字面意思 夭折 请教各位大佬具体细节(感觉和JVM state有关)
/**
* 指定运行其中的Runnable,一般都需要指定,不指定的线程没有意义,或者可以通过创建Thread的子类并重新run方法。
*/
private Runnable target;
/**
* 指定当前线程的线程组,未指定时线程组为创建该线程所属的线程组。
* 线程组可以用来管理一组线程,通过activeCount() 来查看活动线程的数量。感觉除了这个没有什么大的用处。
* 如果有其他用处或理解欢迎留言
*/
private ThreadGroup group;
/**
* 线程用的上下文类加载器,该上下文类加载器可供线程加载类和资源
*/
private ClassLoader contextClassLoader;
/**
* 继承的访问系统资源的上下文(本线程的)
*/
private AccessControlContext inheritedAccessControlContext;
/**
* 计数变量,用在nextThreadNum方法中为匿名线程生成名称
*/
private static int threadInitNumber;
private static synchronized int nextThreadNum() {
return threadInitNumber++;
}
/**
* 线程局部变量
*/
ThreadLocal.ThreadLocalMap threadLocals = null;
/**
* 可继承的线程局部变量 比如一些 logId uid token 什么项目中共用的一些参数及标准
* 如果{true},则从构造线程 继承 (inheritableThreadLocals) 的初始值
* public的构造器 此参数均为true
*/
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
/**
* 新线程预期所需的堆栈大小,或者零表示该参数将被忽略。
* 与平台相关,不建议使用该属性。
*/
private long stackSize;
private long nativeParkEventPointer;//native线程终止后,保持虚拟机私有状态
private long tid;//线程id
private static long threadSeqNumber;//为了生成线程ID
/**
* java线程状态,已初始化,0代表'not yet started'
*/
private volatile int threadStatus = 0;
private static synchronized long nextThreadID() {
return ++threadSeqNumber;
}
/**
* java.util.concurrent.locks.LockSupport.park.是提供给当前调用的参数
* 由 java.util.concurrent.locks.LockSupport.setBlocker 设置
* 通过 java.util.concurrent.locks.LockSupport.getBlocker访问
*/
volatile Object parkBlocker;
/**
* 此线程在 可中断I/O操作中 被阻塞的对象(如果有)。
* 设置此线程的中断状态后,应调用 该对象的中断方法。
*/
private volatile Interruptible blocker;
private final Object blockerLock = new Object();
/* Set the blocker field; invoked via sun.misc.SharedSecrets from java.nio code
*/
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;
/**
* 返回 当前正在执行的线程
*/
public static native Thread currentThread();
/**
* 向调度程序提示当前线程愿意让步,即让出CPU资源和其他线程重新竞争资源
* 感觉没什么用(主动用的情况很少)
*/
public static native void yield();
/**
* 使线程睡眠一段时间,线程挂起,让出CPU资源
* 不会释放锁,因为此操作不依赖加锁 (有锁的话是使用者自己主观意愿,所以需要使用者自己操作释放锁)
*
* @throws InterruptedException 睡眠中的线程被中断会抛出该异常,该异常会清除中断位的状态
*/
public static native void sleep(long millis) 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");
if (nanos >= 500000 || (nanos != 0 && millis == 0)) millis++;
sleep(millis);
}
private void init(ThreadGroup g, Runnable target, String name,
long stackSize) {
init(g, target, name, stackSize, null, true);
}
/**
* 使用当前的AccessControlContext初始化线程。
*/
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) {
//如果有系统安全manager,从manager中获取当前线程的线程组。
if (security != null) g = security.getThreadGroup();
//如果线程组为空,采用父类的线程组
if (g == null) g = parent.getThreadGroup();
}
//校验是否可以访问
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)
//true时继承父类 共用参数
this.inheritableThreadLocals =
ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
this.stackSize = stackSize;
//赋值tid
tid = nextThreadID();
}
/**
* 抛出CloneNotSupportedException,因为无法有意义地通过克隆构造一个新的线程。
*/
@Override
protected Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
public Thread() {
init(null, null, "Thread-" + nextThreadNum(), 0);
}
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
Thread(Runnable target, AccessControlContext acc) {
init(null, target, "Thread-" + nextThreadNum(), 0, acc, false);
}
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);
}
public Thread(ThreadGroup group, Runnable target, String name, long stackSize) {
init(group, target, name, stackSize);
}
/**
* 使线程进入就绪状态,等竞争到CPU资源后执行下面的run()方法
*
* @throws IllegalThreadStateException 线程启动后再次调用会报错
*/
public synchronized void start() {
/**
* VM创建的线程或者系统线程组创建的线程 不是通过此方法创建的. 该方法逻辑可能会变化.
*/
//0是就绪状态 已经是就绪状态,再调用此方法后就会报错
if (threadStatus != 0) throw new IllegalThreadStateException();
//通知线程组 该线程将要启动
group.add(this);
boolean started = false;
try {
//native方法,通过虚拟机启动线程
start0();
started = true;
} finally {
try {
if (!started) {
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
//什么也不做。防止覆盖start0抛出的异常,让该异常向上传递
}
}
}
private native void start0();
/**
* 争抢到CPU资源 线程真正执行的方法
*/
@Override
public void run() {
if (target != null) {
target.run();
}
}
/**
* 系统调用此方法,使线程有机会在线程实际退出之前进行清理。
*/
private void exit() {
if (group != null) {
group.threadTerminated(this);
group = null;
}
target = null;
threadLocals = null;
inheritableThreadLocals = null;
inheritedAccessControlContext = null;
blocker = null;
uncaughtExceptionHandler = null;
}
/**
* 强制退出 (类比 kill -9) 过期方法 已经不建议使用
*/
@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());
}
@Deprecated
public final synchronized void stop(Throwable obj) {
throw new UnsupportedOperationException();
}
/**
* 中断此线程.
*/
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();
}
/**
* 测试当前线程是否已被中断。并且清除线程的 中断状态
* 当前线程已被中断 返回true 并且清除线程的 中断状态(置为false)
*/
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
/**
* 测试当前线程是否已被中断。 和上面方法差别是该方法 不清除线程的中断状态
* 当前线程已被中断 返回true
*/
public boolean isInterrupted() {
return isInterrupted(false);
}
/**
* private 测试当前线程是否已被中断 根据参数看是否需要清楚中断状态
*/
private native boolean isInterrupted(boolean ClearInterrupted);
@Deprecated
public void destroy() {
throw new NoSuchMethodError();
}
/**
* 测试线程是否存活
*/
public final native boolean isAlive();
/**
* 挂起这个线程
*/
@Deprecated
public final void suspend() {
checkAccess();
suspend0();
}
/**
* 恢复挂起的线程
*/
@Deprecated
public final void resume() {
checkAccess();
resume0();
}
/**
* 设置线程优先级
*/
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;
}
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;
}
public final ThreadGroup getThreadGroup() {
return group;
}
/**
* 返回线程组中活动线程数的估计值 是估计值的原因是线程调用了start之后就算在估计值中 并不一定正在执行
*/
public static int activeCount() {
return currentThread().getThreadGroup().activeCount();
}
/**
* 将当前线程的线程组及其子组中的每个活动线程复制到指定的数组中
*/
public static int enumerate(Thread tarray[]) {
return currentThread().getThreadGroup().enumerate(tarray);
}
/**
* 线程必须被挂起 然后计算此线程中的堆栈帧数并返回。
*/
@Deprecated
public native int countStackFrames();
/**
* 最多等待多少时间 使该线程结束
*/
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) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
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);
}
public static void dumpStack() {
new Exception("Stack trace").printStackTrace();
}
public final void setDaemon(boolean on) {
checkAccess();
if (isAlive()) {
throw new IllegalThreadStateException();
}
daemon = on;
}
public final boolean isDaemon() {
return daemon;
}
public final void checkAccess() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkAccess(this);
}
}
public String toString() {
ThreadGroup group = getThreadGroup();
if (group != null) {
return "Thread[" + getName() + "," + getPriority() + "," +
group.getName() + "]";
} else {
return "Thread[" + getName() + "," + getPriority() + "," +
"" + "]";
}
}
@CallerSensitive
public ClassLoader getContextClassLoader() {
if (contextClassLoader == null)
return null;
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
ClassLoader.checkClassLoaderPermission(contextClassLoader,
Reflection.getCallerClass());
}
return contextClassLoader;
}
public void setContextClassLoader(ClassLoader cl) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(new RuntimePermission("setContextClassLoader"));
}
contextClassLoader = cl;
}
/**
* 当且仅当 当前线程 持有入参锁时,才返回 true
*/
public static native boolean holdsLock(Object obj);
private static final StackTraceElement[] EMPTY_STACK_TRACE
= new StackTraceElement[0];
public StackTraceElement[] getStackTrace() {
if (this != Thread.currentThread()) {
// check for getStackTrace permission
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkPermission(
SecurityConstants.GET_STACK_TRACE_PERMISSION);
}
// optimization so we do not call into the vm for threads that
// have not yet started or have terminated
if (!isAlive()) {
return EMPTY_STACK_TRACE;
}
StackTraceElement[][] stackTraceArray = dumpThreads(new Thread[]{this});
StackTraceElement[] stackTrace = stackTraceArray[0];
// a thread that was alive during the previous isAlive call may have
// since terminated, therefore not having a stacktrace.
if (stackTrace == null) {
stackTrace = EMPTY_STACK_TRACE;
}
return stackTrace;
} else {
// Don't need JVM help for current thread
return (new Exception()).getStackTrace();
}
}
public static Map<Thread, StackTraceElement[]> getAllStackTraces() {
// check for getStackTrace permission
SecurityManager security = System.getSecurityManager();
if (security != null) {
security.checkPermission(
SecurityConstants.GET_STACK_TRACE_PERMISSION);
security.checkPermission(
SecurityConstants.MODIFY_THREADGROUP_PERMISSION);
}
// Get a snapshot of the list of all threads
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);
}
// else terminated so we don't put it in the map
}
return m;
}
private static final RuntimePermission SUBCLASS_IMPLEMENTATION_PERMISSION =
new RuntimePermission("enableContextClassLoaderOverride");
private static class Caches {
static final ConcurrentMap<WeakClassKey, Boolean> subclassAudits =
new ConcurrentHashMap<>();
static final ReferenceQueue<Class<?>> subclassAuditsQueue =
new ReferenceQueue<>();
}
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();
}
private static boolean auditSubclass(final Class<?> subcl) {
Boolean result = AccessController.doPrivileged(
new PrivilegedAction<Boolean>() {
public Boolean run() {
for (Class<?> cl = subcl;
cl != Thread.class;
cl = cl.getSuperclass()) {
try {
cl.getDeclaredMethod("getContextClassLoader", new Class<?>[0]);
return Boolean.TRUE;
} catch (NoSuchMethodException ex) {
}
try {
Class<?>[] params = {ClassLoader.class};
cl.getDeclaredMethod("setContextClassLoader", params);
return Boolean.TRUE;
} catch (NoSuchMethodException ex) {
}
}
return Boolean.FALSE;
}
}
);
return result.booleanValue();
}
private native static StackTraceElement[][] dumpThreads(Thread[] threads);
private native static Thread[] getThreads();
public long getId() {
return tid;
}
/**
* NEW:A thread that has not yet started is in this state.
* RUNNABLE:A thread executing in the Java virtual machine is in this state.
* BLOCKED:A thread that is blocked waiting for a monitor lock is in this state.
* WAITING:A thread that is waiting indefinitely for another thread to perform a particular action is in this state.
* TIMED_WAITING:A thread that is waiting for another thread to perform an action for up to a specified waiting time is in this state.
* TERMINATED:A thread that has exited is in this state.
*/
public enum State {
NEW,
RUNNABLE,
BLOCKED,
WAITING,
TIMED_WAITING,
TERMINATED;
}
public State getState() {
// get current thread state
return sun.misc.VM.toThreadState(threadStatus);
}
@FunctionalInterface
public interface UncaughtExceptionHandler {
/**
* Method invoked when the given thread terminates due to the
* given uncaught exception.
* <p>Any exception thrown by this method will be ignored by the
* Java Virtual Machine.
*
* @param t the thread
* @param e the exception
*/
void uncaughtException(Thread t, Throwable e);
}
private volatile UncaughtExceptionHandler uncaughtExceptionHandler;
private static volatile UncaughtExceptionHandler defaultUncaughtExceptionHandler;
public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(
new RuntimePermission("setDefaultUncaughtExceptionHandler")
);
}
defaultUncaughtExceptionHandler = eh;
}
public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler() {
return defaultUncaughtExceptionHandler;
}
public UncaughtExceptionHandler getUncaughtExceptionHandler() {
return uncaughtExceptionHandler != null ?
uncaughtExceptionHandler : group;
}
public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
checkAccess();
uncaughtExceptionHandler = eh;
}
private void dispatchUncaughtException(Throwable e) {
getUncaughtExceptionHandler().uncaughtException(this, e);
}
static void processQueue(ReferenceQueue<Class<?>> queue,
ConcurrentMap<? extends
WeakReference<Class<?>>, ?> map) {
Reference<? extends Class<?>> ref;
while ((ref = queue.poll()) != null) {
map.remove(ref);
}
}
static class WeakClassKey extends WeakReference<Class<?>> {
/**
* saved value of the referent's identity hash code, to maintain
* a consistent hash code after the referent has been cleared
*/
private final int hash;
/**
* Create a new WeakClassKey to the given object, registered
* with a queue.
*/
WeakClassKey(Class<?> cl, ReferenceQueue<Class<?>> refQueue) {
super(cl, refQueue);
hash = System.identityHashCode(cl);
}
/**
* Returns the identity hash code of the original referent.
*/
@Override
public int hashCode() {
return hash;
}
/**
* Returns true if the given object is this identical
* WeakClassKey instance, or, if this object's referent has not
* been cleared, if the given object is another WeakClassKey
* instance with the identical non-null referent as this one.
*/
@Override
public boolean equals(Object obj) {
if (obj == this)
return true;
if (obj instanceof WeakClassKey) {
Object referent = get();
return (referent != null) &&
(referent == ((WeakClassKey) obj).get());
} else {
return false;
}
}
}
@sun.misc.Contended("tlr")
long threadLocalRandomSeed;
@sun.misc.Contended("tlr")
int threadLocalRandomProbe;
@sun.misc.Contended("tlr")
int threadLocalRandomSecondarySeed;
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);
}