创建线程方式
有2种方式可以创建一个可执行线程。
1.继承Thread类。子类可覆写父类的run()方法。子类实例分配内存后可运行(非立即,取决于CPU调用)
class PrimeThread extends Thread {
long minPrime;
PrimeThread(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
...
}
}
启动
PrimeThread p = new PrimeThread(143);
p.start();
2.实现Runnable接口。
此类自己会实现run()方法。然后此线程会被分配内存,当线程被创建时,会传入一个参数,然后开始执行。
class PrimeRun implements Runnable {
long minPrime;
PrimeRun(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
...
}
}
启动
PrimeRun p = new PrimeRun(143);
new Thread(p).start();
线程状态转换
继承关系
源码
public
class Thread implements Runnable {
/**
* 确保本地注册(类构造器方法<clinit>方法用于类初始化)是创建线程首先做的事情
*/
private static native void registerNatives();
static {
registerNatives();
}
/**
* 线程名
*/
private volatile String name;
/**
* 线程优先级,int 表示
*/
private int priority;
private Thread threadQ;
private long eetop;
private boolean single_step;
/**
* 是否是守护线程
* 当所有非守护进程结束或死亡后,程序将停止
*/
private boolean daemon = false;
/**
* JVM状态
*/
private boolean stillborn = false;
/**
* run方法执行的目标代码
*/
private Runnable target;
/**
* 所属线程组
*/
private ThreadGroup group;
/**
* 此类型的类加载器
*/
private ClassLoader contextClassLoader;
/**
* 此线程继承的访问控制上下文
*/
private AccessControlContext inheritedAccessControlContext;
/**
* 用于自动编号的匿名线程
*/
private static int threadInitNumber;
private static synchronized int nextThreadNum() {
return threadInitNumber++;
}
/**
* 此线程的本地变量值
* 此map由ThreadLocal类进行维护,因为这个类在ThreadLocal中是包级私有的
*/
ThreadLocal.ThreadLocalMap threadLocals = null;
/**
* 和此线程相关的由继承得到的本地变量值
*/
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
/**
* 此线程请求栈的深度,如果线程创建者未指定栈深度则其值为0
* 此数字如何被使用完全取决于虚拟机自己;也有一些虚拟机会忽略此变量值
*/
private long stackSize;
/**
* 此变量表示:在本地线程终止后,JVM私有的一个状态值
*/
private long nativeParkEventPointer;
/**
* 线程id
*/
private long tid;
/**
* 用于生成线程ID
*/
private static long threadSeqNumber;
/**
* 线程状态值,初始化值表示当前线程还未运行
*/
private volatile int threadStatus = 0;
/**
* 获取下一个线程id
*/
private static synchronized long nextThreadID() {
return ++threadSeqNumber;
}
/**
* 用于调用 java.util.concurrent.locks.LockSupport.park方法的参数
*/
volatile Object parkBlocker;
/**
* 如果此线程状态被设置为中断状态,则调用此阻塞对象的中断方法
*/
private volatile Interruptible blocker;
private final Object blockerLock = new Object();
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的使用
* <p>
* 让出CPU是一种启发式的尝试,以改善线程之间的相对进展,否则将过度利用CPU
* 此方法很少有适用的场景。当设计并发控制结构(如java.util.concurrent.locks包中的并发结构)时,它可能比较有用
*/
public static native void yield();
/**
* 此方法会引起当前执行线程sleep(临时停止执行)指定毫秒数
* 此方法的调用不会引起当前线程放弃任何监听器(monitor)的所有权(ownership)
*/
public static native void sleep(long millis) throws InterruptedException;
/**
* 同 sleep(long millis)
*/
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);
}
/**
* 初始化一个线程
*
* @param g 线程分组
* @param target run() 方法执行代码
* @param name 线程名
* @param stackSize 值为0表示此参数被忽略
* @param acc 用于继承的访问控制上下文
* @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) {
// 从SecurityManager拿线程组
if (security != null) {
g = security.getThreadGroup();
}
// 如果还没拿到从当前线程拿
if (g == null) {
g = parent.getThreadGroup();
}
}
// 检查是否可获取
g.checkAccess();
// 检查是否有required权限
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);
this.stackSize = stackSize;
// 设置线程ID
tid = nextThreadID();
}
/**
* 线程不支持前拷贝,抛异常
*/
@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);
}
/**
* 执行当前线程,JVM会调用此线程的run()方法
* 就是说当调用该方法后有两个线程并发执行:当前线程(从调用的start方法返回)和另一个线程(它在执行run方法)
* 多次start一个线程会
*
* @throws IllegalThreadStateException 多次start一个线程会
*/
public synchronized void start() {
// //状态校验 0:NEW 新建状态
if (threadStatus != 0)
throw new IllegalThreadStateException();
// 添加进线程组
group.add(this);
boolean started = false;
try {
// 调用native方法执行线程run方法
start0();
started = true;
} finally {
try {
if (!started) {
// 启动失败,从线程组中移除当前前程
group.threadStartFailed(this);
}
} catch (Throwable ignore) {
}
}
}
private native void start0();
/**
* 如果此线程有runable对象,则执行,否则什么也不执行
*/
@Override
public void run() {
if (target != null) {
target.run();
}
}
/**
* 此方法由系统调用,可以使Thread在销毁前释放资源
*/
private void exit() {
if (group != null) {
// 移除线程
group.threadTerminated(this);
group = null;
}
target = null;
threadLocals = null;
inheritableThreadLocals = null;
inheritedAccessControlContext = null;
blocker = null;
uncaughtExceptionHandler = null;
}
@Deprecated
public final void stop() {
SecurityManager security = System.getSecurityManager();
if (security != null) {
checkAccess();
if (this != Thread.currentThread()) {
security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION);
}
}
if (threadStatus != 0) {
resume();
}
stop0(new ThreadDeath());
}
@Deprecated
public final synchronized void stop(Throwable obj) {
throw new UnsupportedOperationException();
}
/**
* 中断当前线程
*
* <p> Unless the current thread is interrupting itself, which is
* always permitted, the {@link #checkAccess() checkAccess} method
* of this thread is invoked, which may cause a {@link
* SecurityException} to be thrown.
*
* <p> If this thread is blocked in an invocation of the {@link
* Object#wait() wait()}, {@link Object#wait(long) wait(long)}, or {@link
* Object#wait(long, int) wait(long, int)} methods of the {@link Object}
* class, or of the {@link #join()}, {@link #join(long)}, {@link
* #join(long, int)}, {@link #sleep(long)}, or {@link #sleep(long, int)},
* methods of this class, then its interrupt status will be cleared and it
* will receive an {@link InterruptedException}.
*
* <p> If this thread is blocked in an I/O operation upon an {@link
* java.nio.channels.InterruptibleChannel InterruptibleChannel}
* then the channel will be closed, the thread's interrupt
* status will be set, and the thread will receive a {@link
* java.nio.channels.ClosedByInterruptException}.
*
* <p> If this thread is blocked in a {@link java.nio.channels.Selector}
* then the thread's interrupt status will be set and it will return
* immediately from the selection operation, possibly with a non-zero
* value, just as if the selector's {@link
* java.nio.channels.Selector#wakeup wakeup} method were invoked.
*
* <p> If none of the previous conditions hold then this thread's interrupt
* status will be set. </p>
*
* <p> Interrupting a thread that is not alive need not have any effect.
*
* @throws SecurityException if the current thread cannot modify this thread
* @revised 6.0
* @spec JSR-51
*/
/**
* 中断当前线程
* <p>
* 除非当前线程在中断自己,否则checkAccess()方法抛出异常SecurityException
* <p>
* 1.如果当前线程由于wait类型方法,join类型方法或者sleep类型的方法的调用被阻塞,则它的中断状态将被清除且会收到一个
* 中断异常InterruptedException
* <p>
* 2.如果此线程由于java.nio.channels.InterruptibleChannel类中的InterruptibleChannel的I/O操作而被阻塞,
* 则此方法会导致通道被关闭,且线程的中断状态会被重置,同时线程会收到一个异常ClosedByInterruptException。
* <p>
* 3.如果此线程由于java.nio.channels.Selector而阻塞,则线程的中断状态会被重置,且它将立即从阻塞的selection操作返回,
* 且返回值通常是一个非零值,这就和java.nio.channels.Selector#wakeup的wakeup()方法被调用一样。
* <p>
* 4.如果前面的条件都不成立,那么该线程的中断状态将被重置。
* <p>
* 中断一个处于非活着状态的线程并不需要产生任何其它影响
**/
public void interrupt() {
if (this != Thread.currentThread())
checkAccess();
// 对阻塞锁使用同步机制
synchronized (blockerLock) {
Interruptible b = blocker;
if (b != null) {
interrupt0(); // 只是为了设定中断标识位
b.interrupt(this); // 中断当前线程
return;
}
}
interrupt0(); // 只是为了设定中断标识位
}
/**
* 返回当前线程中断状态,调用方法后线程中断状态会被清除
* 也就是调用两次,第二次会返回false
*/
public static boolean interrupted() {
return currentThread().isInterrupted(true);
}
/**
* 返回当前线程中断状态,调用方法后线程中断状态不会被清除
*/
public boolean isInterrupted() {
return isInterrupted(false);
}
/**
* 返回当前线程中断状态
*/
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;
}
/**
* 返回所属线程组的线程数
*/
public static int activeCount() {
return currentThread().getThreadGroup().activeCount();
}
public static int enumerate(Thread tarray[]) {
return currentThread().getThreadGroup().enumerate(tarray);
}
@Deprecated
public native int countStackFrames();
/**
* 最多等待参数millis(ms)时长当前线程就会死亡。参数为0时则要持续等待
* <p>
* 此方法在实现上:循环调用wait()方法,当线程终止时notifyAll()方法会被调用
* 建议应用程序不要在线程实例上使用wait,notify,notifyAll方法.
*/
public final synchronized void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
// 如果等待时间<0,则抛出异常
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
// 等待时间为0
while (isAlive()) {
wait(0);
}
} else {
// 指定等待时间
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
// 超时返回
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
/**
* 同 join(long millis)
*/
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();
}
/**
* 将当前线程设定为守护线程,此方法在start前被调用
*/
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();
}
}
/**
* 返回一个所有存活线程的栈跟踪信息的Map
*/
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 {
/**
* cache of subclass security audit results
*/
static final ConcurrentMap<Thread.WeakClassKey, Boolean> subclassAudits =
new ConcurrentHashMap<>();
/**
* queue for WeakReferences to audited subclasses
*/
static final ReferenceQueue<Class<?>> subclassAuditsQueue =
new ReferenceQueue<>();
}
/**
* Verifies that this (possibly subclass) instance can be constructed
* without violating security constraints: the subclass must not override
* security-sensitive non-final methods, or else the
* "enableContextClassLoaderOverride" RuntimePermission is checked.
*/
private static boolean isCCLOverridden(Class<?> cl) {
if (cl == Thread.class)
return false;
processQueue(Caches.subclassAuditsQueue, Thread.Caches.subclassAudits);
Thread.WeakClassKey key = new Thread.WeakClassKey(cl, Thread.Caches.subclassAuditsQueue);
Boolean result = Thread.Caches.subclassAudits.get(key);
if (result == null) {
result = Boolean.valueOf(auditSubclass(cl));
Thread.Caches.subclassAudits.putIfAbsent(key, result);
}
return result.booleanValue();
}
/**
* Performs reflective checks on given subclass to verify that it doesn't
* override security-sensitive non-final methods. Returns true if the
* subclass overrides any of the methods, false otherwise.
*/
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();
/**
* 返回当前线程ID
*/
public long getId() {
return tid;
}
/**
* 表示线程状态。有如下几种:
* 1.NEW:表示:线程还未开始,只是进行了一些线程创建的初始化操作,但未调用start()方法
* 2.RUNNABLE:线程在JVM里面处于运行状态(这里就绪和运行同属于运行)
* 3.BLOCKED:线程正在等待一个监视器锁,处于阻塞状态
* 4.WAITING:一个线程在等待另一个线程的特定操作(通知or中断),这种等待是无限期的
* 5.TIMED_WAITING:一个线程在等待另一个线程的特定操作,这种等待是有时间限制的。一旦超时则线程自行返回
* 6.TERMINATED:线程已退出.表示线程已经执行完毕
* <p>
* 线程在某一时刻,只能处于上述6个状态的某一个。这些状态值是虚拟机状态值,因而并不会反映操作系统的线程状态。
*/
public enum State {
NEW,
/**
* 线程可以正在运行,也可以处于就绪状态等待获得CPU
*/
RUNNABLE,
/**
* 在调用完wait()方法后进入
*/
BLOCKED,
/**
* 一个线程处于wating状态,是因为调用了下面方法中的某一个:
* 1.Object.wait
* 2.Thread.join
* 3.LockSupport.park
* <p>
* 其它线程的特定操作包括 :notify(),notifyAll(),join()等.
*/
WAITING,
/**
* 线程等待指定时间.
* 这种状态的出现是因为调用了下面方法中的某一个:
* 1.Thread.sleep()
* 2.Object.wait()
* 3.Thread.join()
* 4.LockSupport.parkNanos()
* 5.LockSupport.parkUntil()
*/
TIMED_WAITING,
TERMINATED;
}
/**
* 返回线程状态
*/
public Thread.State getState() {
// get current thread state
return sun.misc.VM.toThreadState(threadStatus);
}
// Added in JSR-166
/**
* Interface for handlers invoked when a <tt>Thread</tt> abruptly
* terminates due to an uncaught exception.
* <p>When a thread is about to terminate due to an uncaught exception
* the Java Virtual Machine will query the thread for its
* <tt>UncaughtExceptionHandler</tt> using
* {@link #getUncaughtExceptionHandler} and will invoke the handler's
* <tt>uncaughtException</tt> method, passing the thread and the
* exception as arguments.
* If a thread has not had its <tt>UncaughtExceptionHandler</tt>
* explicitly set, then its <tt>ThreadGroup</tt> object acts as its
* <tt>UncaughtExceptionHandler</tt>. If the <tt>ThreadGroup</tt> object
* has no
* special requirements for dealing with the exception, it can forward
* the invocation to the {@linkplain #getDefaultUncaughtExceptionHandler
* default uncaught exception handler}.
*
* @see #setDefaultUncaughtExceptionHandler
* @see #setUncaughtExceptionHandler
* @see ThreadGroup#uncaughtException
* @since 1.5
*/
@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);
}
// null unless explicitly set
private volatile Thread.UncaughtExceptionHandler uncaughtExceptionHandler;
// null unless explicitly set
private static volatile Thread.UncaughtExceptionHandler defaultUncaughtExceptionHandler;
/**
* Set the default handler invoked when a thread abruptly terminates
* due to an uncaught exception, and no other handler has been defined
* for that thread.
*
* <p>Uncaught exception handling is controlled first by the thread, then
* by the thread's {@link ThreadGroup} object and finally by the default
* uncaught exception handler. If the thread does not have an explicit
* uncaught exception handler set, and the thread's thread group
* (including parent thread groups) does not specialize its
* <tt>uncaughtException</tt> method, then the default handler's
* <tt>uncaughtException</tt> method will be invoked.
* <p>By setting the default uncaught exception handler, an application
* can change the way in which uncaught exceptions are handled (such as
* logging to a specific device, or file) for those threads that would
* already accept whatever "default" behavior the system
* provided.
*
* <p>Note that the default uncaught exception handler should not usually
* defer to the thread's <tt>ThreadGroup</tt> object, as that could cause
* infinite recursion.
*
* @param eh the object to use as the default uncaught exception handler.
* If <tt>null</tt> then there is no default handler.
* @throws SecurityException if a security manager is present and it
* denies <tt>{@link RuntimePermission}
* ("setDefaultUncaughtExceptionHandler")</tt>
* @see #setUncaughtExceptionHandler
* @see #getUncaughtExceptionHandler
* @see ThreadGroup#uncaughtException
* @since 1.5
*/
public static void setDefaultUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh) {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
sm.checkPermission(
new RuntimePermission("setDefaultUncaughtExceptionHandler")
);
}
defaultUncaughtExceptionHandler = eh;
}
/**
* Returns the default handler invoked when a thread abruptly terminates
* due to an uncaught exception. If the returned value is <tt>null</tt>,
* there is no default.
*
* @return the default uncaught exception handler for all threads
* @see #setDefaultUncaughtExceptionHandler
* @since 1.5
*/
public static Thread.UncaughtExceptionHandler getDefaultUncaughtExceptionHandler() {
return defaultUncaughtExceptionHandler;
}
/**
* Returns the handler invoked when this thread abruptly terminates
* due to an uncaught exception. If this thread has not had an
* uncaught exception handler explicitly set then this thread's
* <tt>ThreadGroup</tt> object is returned, unless this thread
* has terminated, in which case <tt>null</tt> is returned.
*
* @return the uncaught exception handler for this thread
* @since 1.5
*/
public Thread.UncaughtExceptionHandler getUncaughtExceptionHandler() {
return uncaughtExceptionHandler != null ?
uncaughtExceptionHandler : group;
}
/**
* Set the handler invoked when this thread abruptly terminates
* due to an uncaught exception.
* <p>A thread can take full control of how it responds to uncaught
* exceptions by having its uncaught exception handler explicitly set.
* If no such handler is set then the thread's <tt>ThreadGroup</tt>
* object acts as its handler.
*
* @param eh the object to use as this thread's uncaught exception
* handler. If <tt>null</tt> then this thread has no explicit handler.
* @throws SecurityException if the current thread is not allowed to
* modify this thread.
* @see #setDefaultUncaughtExceptionHandler
* @see ThreadGroup#uncaughtException
* @since 1.5
*/
public void setUncaughtExceptionHandler(Thread.UncaughtExceptionHandler eh) {
checkAccess();
uncaughtExceptionHandler = eh;
}
/**
* Dispatch an uncaught exception to the handler. This method is
* intended to be called only by the JVM.
*/
private void dispatchUncaughtException(Throwable e) {
getUncaughtExceptionHandler().uncaughtException(this, e);
}
/**
* Removes from the specified map any keys that have been enqueued
* on the specified reference queue.
*/
static void processQueue(ReferenceQueue<Class<?>> queue,
ConcurrentMap<? extends
WeakReference<Class<?>>, ?> map) {
Reference<? extends Class<?>> ref;
while ((ref = queue.poll()) != null) {
map.remove(ref);
}
}
/**
* Weak key for Class objects.
**/
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 Thread.WeakClassKey) {
Object referent = get();
return (referent != null) &&
(referent == ((Thread.WeakClassKey) obj).get());
} else {
return false;
}
}
}
// The following three initially uninitialized fields are exclusively
// managed by class java.util.concurrent.ThreadLocalRandom. These
// fields are used to build the high-performance PRNGs in the
// concurrent code, and we can not risk accidental false sharing.
// Hence, the fields are isolated with @Contended.
/**
* The current seed for a ThreadLocalRandom
*/
@sun.misc.Contended("tlr")
long threadLocalRandomSeed;
/**
* Probe hash value; nonzero if threadLocalRandomSeed initialized
*/
@sun.misc.Contended("tlr")
int threadLocalRandomProbe;
/**
* Secondary seed isolated from public ThreadLocalRandom sequence
*/
@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);
}
注意点
每个线程都有一个用于目的标识的名字。多个线程可以有相同的名字。线程被创建时如果名字没有被指定,则系统为其自动生成一个新的名字。
多次调用start方法会报异常 IllegalThreadStateException。
最低优先级为1,默认优先级为5,最高优先级为10。
ThreadGroup 并不能提供对线程的管理,主要功能是对线程进行组织,创建线程的时候如果没有显式的指定 ThreadGroup,那么新的线程将会默认加入与父线程相同的线程组中。
参考 https://blog.csdn.net/caoxiaohong1005/article/details/80312396