死磕JDK源码之Thread

  1 package java.lang;
  2 
  3 import java.lang.ref.Reference;
  4 import java.lang.ref.ReferenceQueue;
  5 import java.lang.ref.WeakReference;
  6 import java.security.AccessController;
  7 import java.security.AccessControlContext;
  8 import java.security.PrivilegedAction;
  9 import java.util.Map;
 10 import java.util.HashMap;
 11 import java.util.concurrent.ConcurrentHashMap;
 12 import java.util.concurrent.ConcurrentMap;
 13 import java.util.concurrent.locks.LockSupport;
 14 
 15 import sun.nio.ch.Interruptible;
 16 import sun.reflect.CallerSensitive;
 17 import sun.reflect.Reflection;
 18 import sun.security.util.SecurityConstants;
 19 
 20 /*
 21 Every thread has a priority. Threads with higher priority are executed in preference to threads
 22 with lower priority.
 23 Each thread may or may not also be marked as a daemon. When code running in some thread creates a
 24 new <code>Thread</code> object,the new thread has its priority initially set equal to the priority
 25 of the creating thread, and is a daemon thread if and only if the creating thread is a daemon.
 26 
 27 When a Java Virtual Machine starts up, there is usually a single non-daemon thread (which typically
 28 calls the method named <code>main</code> of some designated class). The Java Virtual Machine continues
 29 to execute threads until either of the following occurs:
 30 1.The <code>exit</code> method of class <code>Runtime</code> has been called and the security manager
 31 has permitted the exit operation to take place.
 32 2.All threads that are not daemon threads have died, either by returning from the call to the
 33 <code>run</code> method or by throwing an exception that propagates beyond the <code>run</code> method.
 34 
 35 Every thread has a name for identification purposes. More than one thread may have the same name. If a name
 36 is not specified when a thread is created, a new name is generated for it.Unless otherwise noted, passing a
 37 {@code null} argument to a constructor or method in this class will cause a {@link NullPointerException} to be thrown.
 38 */
 39 public class Thread implements Runnable {
 40     private static native void registerNatives();
 41 
 42     static {
 43         registerNatives();
 44     }
 45 
 46     private volatile char name[];
 47     private int priority;
 48     private Thread threadQ;
 49     private long eetop;
 50 
 51     //是否单步执行线程
 52     private boolean single_step;
 53 
 54     //是否为守护线程
 55     private boolean daemon = false;
 56 
 57     //JVM状态
 58     private boolean stillborn = false;
 59 
 60     //run方法执行的目标代码
 61     private Runnable target;
 62 
 63     //线程所属的线程组
 64     private ThreadGroup group;
 65 
 66     //线程的类加载器
 67     private ClassLoader contextClassLoader;
 68 
 69     //线程继承的AccessControlContext
 70     private AccessControlContext inheritedAccessControlContext;
 71 
 72     //默认生成的线程名"Thread-" + nextThreadNum()
 73     private static int threadInitNumber;
 74 
 75     private static synchronized int nextThreadNum() {
 76         return threadInitNumber++;
 77     }
 78 
 79     ThreadLocal.ThreadLocalMap threadLocals = null;
 80 
 81     ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
 82 
 83     //线程请求栈的深度,如果线程创建者未指定栈深度则其值为0,stackSize如何用完全取决于虚拟机,有的虚拟机会忽略stackSize
 84     private long stackSize;
 85 
 86     //本地线程终止后,JVM私有的值
 87     private long nativeParkEventPointer;
 88 
 89     //线程id
 90     private long tid;
 91 
 92     //用于生成线程ID
 93     private static long threadSeqNumber;
 94 
 95     //为工具提供的线程状态值,0表示当前线程还未运行
 96     private volatile int threadStatus = 0;
 97 
 98     //获取下一个线程tid
 99     private static synchronized long nextThreadID() {
100         return ++threadSeqNumber;
101     }
102 
103     /*
104     parkBlocker用于调用java.util.concurrent.locks.LockSupport.park方法
105     通过java.util.concurrent.locks.LockSupport.setBlocker方法set
106     通过java.util.concurrent.locks.LockSupport.getBlocker方法get
107     */
108     volatile Object parkBlocker;
109 
110     /*
111     The object in which this thread is blocked in an interruptible I/O operation, if any.
112     The blocker's interrupt method should be invoked after setting this thread's interrupt status.
113     */
114     private volatile Interruptible blocker;
115     private final Object blockerLock = new Object();
116 
117     void blockedOn(Interruptible b) {
118         synchronized (blockerLock) {
119             blocker = b;
120         }
121     }
122 
123     //线程的最低优先级
124     public final static int MIN_PRIORITY = 1;
125 
126     //线程的默认优先级
127     public final static int NORM_PRIORITY = 5;
128 
129     //线程的最高优先级
130     public final static int MAX_PRIORITY = 10;
131 
132     //返回当前正在执行线程对象的引用
133     public static native Thread currentThread();
134 
135     /*
136     A hint to the scheduler that the current thread is willing to yield
137     its current use of a processor. The scheduler is free to ignore this hint.
138     */
139     public static native void yield();
140 
141     //调用sleep方法会使得当前线程临时停止执行指定毫秒数,sleep不释放锁
142     public static native void sleep(long millis) throws InterruptedException;
143 
144     public static void sleep(long millis, int nanos)
145             throws InterruptedException {
146         if (millis < 0) {
147             throw new IllegalArgumentException("timeout value is negative");
148         }
149 
150         if (nanos < 0 || nanos > 999999) {
151             throw new IllegalArgumentException(
152                     "nanosecond timeout value out of range");
153         }
154 
155         if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
156             millis++;
157         }
158 
159         sleep(millis);
160     }
161 
162     private void init(ThreadGroup g, Runnable target, String name,
163                       long stackSize) {
164         init(g, target, name, stackSize, null);
165     }
166 
167     private void init(ThreadGroup g, Runnable target, String name,
168                       long stackSize, AccessControlContext acc) {
169         if (name == null) {
170             throw new NullPointerException("name cannot be null");
171         }
172 
173         this.name = name.toCharArray();
174 
175         Thread parent = currentThread();
176         SecurityManager security = System.getSecurityManager();
177         if (g == null) {
178             if (security != null) {
179                 g = security.getThreadGroup();
180             }
181 
182             if (g == null) {
183                 g = parent.getThreadGroup();
184             }
185         }
186 
187         g.checkAccess();
188 
189         if (security != null) {
190             if (isCCLOverridden(getClass())) {
191                 security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
192             }
193         }
194 
195         g.addUnstarted();
196 
197         this.group = g;
198         this.daemon = parent.isDaemon();
199         this.priority = parent.getPriority();
200         if (security == null || isCCLOverridden(parent.getClass()))
201             this.contextClassLoader = parent.getContextClassLoader();
202         else
203             this.contextClassLoader = parent.contextClassLoader;
204         this.inheritedAccessControlContext =
205                 acc != null ? acc : AccessController.getContext();
206         this.target = target;
207         setPriority(priority);
208         if (parent.inheritableThreadLocals != null)
209             this.inheritableThreadLocals =
210                     ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
211         this.stackSize = stackSize;
212 
213         tid = nextThreadID();
214     }
215 
216     //线程不支持Object的浅拷贝,取而代之的是构造一个新的线程
217     @Override
218     protected Object clone() throws CloneNotSupportedException {
219         throw new CloneNotSupportedException();
220     }
221 
222     public Thread() {
223         init(null, null, "Thread-" + nextThreadNum(), 0);
224     }
225 
226     public Thread(Runnable target) {
227         init(null, target, "Thread-" + nextThreadNum(), 0);
228     }
229 
230     Thread(Runnable target, AccessControlContext acc) {
231         init(null, target, "Thread-" + nextThreadNum(), 0, acc);
232     }
233 
234     public Thread(ThreadGroup group, Runnable target) {
235         init(group, target, "Thread-" + nextThreadNum(), 0);
236     }
237 
238     public Thread(String name) {
239         init(null, null, name, 0);
240     }
241 
242     public Thread(ThreadGroup group, String name) {
243         init(group, null, name, 0);
244     }
245 
246     public Thread(Runnable target, String name) {
247         init(null, target, name, 0);
248     }
249 
250     public Thread(ThreadGroup group, Runnable target, String name) {
251         init(group, target, name, 0);
252     }
253 
254     public Thread(ThreadGroup group, Runnable target, String name,
255                   long stackSize) {
256         init(group, target, name, stackSize);
257     }
258 
259     /*
260     Causes this thread to begin execution; the Java Virtual Machine calls
261     the <code>run</code> method of this thread.
262     The result is that two threads are running concurrently: the current thread
263     (which returns from the call to the <code>start</code> method) and the other
264     thread (which executes its <code>run</code> method).
265 
266     public class ThreadTest {
267         public static void main(String[] args) throws InterruptedException {
268             Thread t1=new Thread(new Runnable() {
269                 @Override
270                 public void run() {
271                     System.out.println("sakura");
272                 }
273             });
274             t1.start();
275             t1.join();
276             t1.start();
277         }
278     }
279 
280     sakura
281     Exception in thread "main" java.lang.IllegalThreadStateException
282         at java.lang.Thread.start(Thread.java:705)
283         at ThreadTest.main(ThreadTest.java:11)
284      */
285     public synchronized void start() {
286         //threadStatus=0表示线程处于NEW状态
287         if (threadStatus != 0)
288             throw new IllegalThreadStateException();
289 
290         group.add(this);
291 
292         boolean started = false;
293         try {
294             start0();
295             started = true;
296         } finally {
297             try {
298                 if (!started) {
299                     group.threadStartFailed(this);
300                 }
301             } catch (Throwable ignore) {
302 
303             }
304         }
305     }
306 
307     private native void start0();
308 
309     @Override
310     public void run() {
311         if (target != null) {
312             target.run();
313         }
314     }
315 
316     //This method is called by the system to give a Thread a chance to clean up before it actually exits.
317     private void exit() {
318         if (group != null) {
319             group.threadTerminated(this);
320             group = null;
321         }
322         target = null;
323         threadLocals = null;
324         inheritableThreadLocals = null;
325         inheritedAccessControlContext = null;
326         blocker = null;
327         uncaughtExceptionHandler = null;
328     }
329 
330     @Deprecated
331     public final void stop() {
332         SecurityManager security = System.getSecurityManager();
333         if (security != null) {
334             checkAccess();
335             if (this != Thread.currentThread()) {
336                 security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION);
337             }
338         }
339         if (threadStatus != 0) {
340             resume();
341         }
342 
343         stop0(new ThreadDeath());
344     }
345 
346     @Deprecated
347     public final synchronized void stop(Throwable obj) {
348         throw new UnsupportedOperationException();
349     }
350 
351     /*
352     中断当前线程,如果不是当前线程中断自己,会调用checkAccess方法,这可能会抛出SecurityException
353     1.如果当前线程由于调用wait、join或sleep方法而阻塞,则中断状态会被清除且会抛出InterruptedException
354     2.如果线程由于java.nio.channels.InterruptibleChannel类中的InterruptibleChannel的I/O操作而被阻塞,
355     调用interrupt方法会使通道关闭且线程的中断状态会被重置并抛出ClosedByInterruptException
356     3.如果当前线程由于java.nio.channels.Selector而被阻塞,则线程的中断状态会被重置,且会立即从selection操作
357     返回一个非零值,这就和java.nio.channels.Selector的wakeup()方法被调用一样
358     如果以上条件都不成立,那么线程的中断状态被重置,中断一个非活跃线程不产生影响
359     */
360     public void interrupt() {
361         if (this != Thread.currentThread())
362             checkAccess();
363 
364         synchronized (blockerLock) {
365             Interruptible b = blocker;
366             if (b != null) {
367                 interrupt0();
368                 b.interrupt(this);
369                 return;
370             }
371         }
372         interrupt0();
373     }
374 
375     /*
376     测试当前线程是否被中断,并且清除中断状态
377     In other words, if this method were to be called twice in succession, the second
378     call would return false (unless the current thread were interrupted again, after
379     the first call had cleared its interrupted status and before the second call had examined it).
380 
381     A thread interruption ignored because a thread was not alive at the time of the interrupt will
382     be reflected by this method returning false.
383     */
384     public static boolean interrupted() {
385         return currentThread().isInterrupted(true);
386     }
387 
388     //测试当前线程是否被中断,但不清除中断状态
389     public boolean isInterrupted() {
390         return isInterrupted(false);
391     }
392 
393     private native boolean isInterrupted(boolean ClearInterrupted);
394 
395     @Deprecated
396     public void destroy() {
397         throw new NoSuchMethodError();
398     }
399 
400     /*
401     判断线程是否处于存活状态
402     A thread is alive if it has been started and has not yet died.
403     */
404     public final native boolean isAlive();
405 
406     @Deprecated
407     public final void suspend() {
408         checkAccess();
409         suspend0();
410     }
411 
412     @Deprecated
413     public final void resume() {
414         checkAccess();
415         resume0();
416     }
417 
418     //设置线程的优先级
419     public final void setPriority(int newPriority) {
420         ThreadGroup g;
421         checkAccess();
422         if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
423             throw new IllegalArgumentException();
424         }
425         if ((g = getThreadGroup()) != null) {
426             if (newPriority > g.getMaxPriority()) {
427                 newPriority = g.getMaxPriority();
428             }
429             setPriority0(priority = newPriority);
430         }
431     }
432 
433     //返回线程优先级
434     public final int getPriority() {
435         return priority;
436     }
437 
438     //设置线程的name
439     public final synchronized void setName(String name) {
440         checkAccess();
441         this.name = name.toCharArray();
442         if (threadStatus != 0) {
443             setNativeName(name);
444         }
445     }
446 
447     //返回线程的name
448     public final String getName() {
449         return new String(name, true);
450     }
451 
452     //返回线程所属的线程组,如果线程已经died,那么会返回null
453     public final ThreadGroup getThreadGroup() {
454         return group;
455     }
456 
457     //返回当前线程所在线程组的线程数的估计值
458     public static int activeCount() {
459         return currentThread().getThreadGroup().activeCount();
460     }
461 
462     public static int enumerate(Thread tarray[]) {
463         return currentThread().getThreadGroup().enumerate(tarray);
464     }
465 
466     @Deprecated
467     public native int countStackFrames();
468 
469     /*
470     最多等待millis时长当前线程就会死亡,millis=0则要持续等待
471     It is recommended that applications not use {@code wait},
472     {@code notify}, or {@code notifyAll} on {@code Thread} instances.
473     */
474     public final synchronized void join(long millis)
475             throws InterruptedException {
476         long base = System.currentTimeMillis();
477         long now = 0;
478 
479         if (millis < 0) {
480             throw new IllegalArgumentException("timeout value is negative");
481         }
482 
483         if (millis == 0) {
484             while (isAlive()) {
485                 wait(0);
486             }
487         } else {
488             while (isAlive()) {
489                 long delay = millis - now;
490                 if (delay <= 0) {
491                     break;
492                 }
493                 wait(delay);
494                 now = System.currentTimeMillis() - base;
495             }
496         }
497     }
498 
499     //最多等待millis微秒+nanos纳秒时长当前线程就会死亡
500     public final synchronized void join(long millis, int nanos)
501             throws InterruptedException {
502 
503         if (millis < 0) {
504             throw new IllegalArgumentException("timeout value is negative");
505         }
506 
507         if (nanos < 0 || nanos > 999999) {
508             throw new IllegalArgumentException(
509                     "nanosecond timeout value out of range");
510         }
511 
512         if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
513             millis++;
514         }
515 
516         join(millis);
517     }
518 
519     //等待一直到线程死亡
520     public final void join() throws InterruptedException {
521         join(0);
522     }
523 
524     /*
525     Prints a stack trace of the current thread to the standard error stream.
526     This method is used only for debugging.
527     */
528     public static void dumpStack() {
529         new Exception("Stack trace").printStackTrace();
530     }
531 
532     /*
533     设置当前线程为守护线程或用户线程
534     只有当所有运行中的线程都为守护线程时JVM才会退出
535     setDaemon方法必须在线程调用start方法之前调用
536     */
537     public final void setDaemon(boolean on) {
538         checkAccess();
539         if (isAlive()) {
540             throw new IllegalThreadStateException();
541         }
542         daemon = on;
543     }
544 
545     //判断当前线程是否为守护线程
546     public final boolean isDaemon() {
547         return daemon;
548     }
549 
550     //确定当前运行线程是否具有修改线程的权限
551     public final void checkAccess() {
552         SecurityManager security = System.getSecurityManager();
553         if (security != null) {
554             security.checkAccess(this);
555         }
556     }
557 
558     public String toString() {
559         ThreadGroup group = getThreadGroup();
560         if (group != null) {
561             return "Thread[" + getName() + "," + getPriority() + "," +
562                     group.getName() + "]";
563         } else {
564             return "Thread[" + getName() + "," + getPriority() + "," +
565                     "" + "]";
566         }
567     }
568 
569     //获取当前线程的ClassLoader
570     @CallerSensitive
571     public ClassLoader getContextClassLoader() {
572         if (contextClassLoader == null)
573             return null;
574         SecurityManager sm = System.getSecurityManager();
575         if (sm != null) {
576             ClassLoader.checkClassLoaderPermission(contextClassLoader,
577                     Reflection.getCallerClass());
578         }
579         return contextClassLoader;
580     }
581 
582     //设置当前线程的ClassLoader
583     public void setContextClassLoader(ClassLoader cl) {
584         SecurityManager sm = System.getSecurityManager();
585         if (sm != null) {
586             sm.checkPermission(new RuntimePermission("setContextClassLoader"));
587         }
588         contextClassLoader = cl;
589     }
590 
591     //当且仅当当前线程持有指定对象的监听器锁时,返回true,用于断言:assert Thread.holdsLock(obj);
592     public static native boolean holdsLock(Object obj);
593 
594     private static final StackTraceElement[] EMPTY_STACK_TRACE
595             = new StackTraceElement[0];
596 
597     /*
598     返回当前线程堆栈转储的堆栈跟踪元素数组
599     如果线程没有start、已经start但没有被调度器调度或已经终止,那么数组长度为0
600     如果数组长度非0,那么数组的第一个元素(索引为0)表示栈的顶部,最后一个元素表示栈底
601     */
602     public StackTraceElement[] getStackTrace() {
603         if (this != Thread.currentThread()) {
604             SecurityManager security = System.getSecurityManager();
605             if (security != null) {
606                 security.checkPermission(
607                         SecurityConstants.GET_STACK_TRACE_PERMISSION);
608             }
609 
610             if (!isAlive()) {
611                 return EMPTY_STACK_TRACE;
612             }
613             StackTraceElement[][] stackTraceArray = dumpThreads(new Thread[]{this});
614             StackTraceElement[] stackTrace = stackTraceArray[0];
615 
616             if (stackTrace == null) {
617                 stackTrace = EMPTY_STACK_TRACE;
618             }
619             return stackTrace;
620         } else {
621             return (new Exception()).getStackTrace();
622         }
623     }
624 
625     //返回所有存活线程的堆栈跟踪数组的map,由于getAllStackTraces时线程仍在执行,所以得到的结果仅仅是一个快照
626     public static Map<Thread, StackTraceElement[]> getAllStackTraces() {
627         SecurityManager security = System.getSecurityManager();
628         if (security != null) {
629             security.checkPermission(
630                     SecurityConstants.GET_STACK_TRACE_PERMISSION);
631             security.checkPermission(
632                     SecurityConstants.MODIFY_THREADGROUP_PERMISSION);
633         }
634 
635         Thread[] threads = getThreads();
636         StackTraceElement[][] traces = dumpThreads(threads);
637         Map<Thread, StackTraceElement[]> m = new HashMap<>(threads.length);
638         for (int i = 0; i < threads.length; i++) {
639             StackTraceElement[] stackTrace = traces[i];
640             if (stackTrace != null) {
641                 m.put(threads[i], stackTrace);
642             }
643         }
644         return m;
645     }
646 
647 
648     private static final RuntimePermission SUBCLASS_IMPLEMENTATION_PERMISSION =
649             new RuntimePermission("enableContextClassLoaderOverride");
650 
651     //Replace with ConcurrentReferenceHashMap when/if it appears in a future release
652     private static class Caches {
653         //子类安全审核结果的缓存
654         static final ConcurrentMap<WeakClassKey, Boolean> subclassAudits =
655                 new ConcurrentHashMap<>();
656 
657         //审核子类的弱引用队列
658         static final ReferenceQueue<Class<?>> subclassAuditsQueue =
659                 new ReferenceQueue<>();
660     }
661 
662     private static boolean isCCLOverridden(Class<?> cl) {
663         if (cl == Thread.class)
664             return false;
665 
666         processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits);
667         WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue);
668         Boolean result = Caches.subclassAudits.get(key);
669         if (result == null) {
670             result = Boolean.valueOf(auditSubclass(cl));
671             Caches.subclassAudits.putIfAbsent(key, result);
672         }
673 
674         return result.booleanValue();
675     }
676 
677     private static boolean auditSubclass(final Class<?> subcl) {
678         Boolean result = AccessController.doPrivileged(
679                 new PrivilegedAction<Boolean>() {
680                     public Boolean run() {
681                         for (Class<?> cl = subcl;
682                              cl != Thread.class;
683                              cl = cl.getSuperclass()) {
684                             try {
685                                 cl.getDeclaredMethod("getContextClassLoader", new Class<?>[0]);
686                                 return Boolean.TRUE;
687                             } catch (NoSuchMethodException ex) {
688                             }
689                             try {
690                                 Class<?>[] params = {ClassLoader.class};
691                                 cl.getDeclaredMethod("setContextClassLoader", params);
692                                 return Boolean.TRUE;
693                             } catch (NoSuchMethodException ex) {
694                             }
695                         }
696                         return Boolean.FALSE;
697                     }
698                 }
699         );
700         return result.booleanValue();
701     }
702 
703     private native static StackTraceElement[][] dumpThreads(Thread[] threads);
704 
705     private native static Thread[] getThreads();
706 
707     /*
708     返回当前线程的tid,线程的tid是一个在线程创建时生成的long类型正数
709     线程的tid在其生命周期内不会更改且独一无二,当一个线程终止时,tid可以被重用
710     */
711     public long getId() {
712         return tid;
713     }
714 
715     //任一时刻线程只能处于其中的一个状态,且只是虚拟机的状态值,并不会反映操作系统的线程状态
716     public enum State {
717         //线程没有调用start方法之前的状态
718         NEW,
719 
720         //线程在JVM里面运行的状态,包括就绪和运行
721         RUNNABLE,
722 
723         //线程等待监视器锁的状态
724         BLOCKED,
725 
726         /*
727         一个线程等待其他线程的状态,这种等待是无限期的
728         Object.wait with no timeout
729         Thread.join with no timeout
730         LockSupport.park
731         */
732         WAITING,
733 
734         /*
735         一个线程等待其他线程的状态,这种等待是有时间限制的
736         Thread.sleep
737         Object.wait with timeout
738         Thread.join with timeout
739         LockSupport.parkNanos
740         LockSupport.parkUntil
741         */
742         TIMED_WAITING,
743 
744         //线程执行完毕已经退出的状态
745         TERMINATED;
746     }
747 
748     //返回当前线程的状态
749     public State getState() {
750         return sun.misc.VM.toThreadState(threadStatus);
751     }
752 
753     @FunctionalInterface
754     public interface UncaughtExceptionHandler {
755         void uncaughtException(Thread t, Throwable e);
756     }
757 
758     private volatile UncaughtExceptionHandler uncaughtExceptionHandler;
759 
760     private static volatile UncaughtExceptionHandler defaultUncaughtExceptionHandler;
761 
762     public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
763         SecurityManager sm = System.getSecurityManager();
764         if (sm != null) {
765             sm.checkPermission(
766                     new RuntimePermission("setDefaultUncaughtExceptionHandler")
767             );
768         }
769 
770         defaultUncaughtExceptionHandler = eh;
771     }
772 
773     public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler() {
774         return defaultUncaughtExceptionHandler;
775     }
776 
777     public UncaughtExceptionHandler getUncaughtExceptionHandler() {
778         return uncaughtExceptionHandler != null ?
779                 uncaughtExceptionHandler : group;
780     }
781 
782     public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
783         checkAccess();
784         uncaughtExceptionHandler = eh;
785     }
786 
787     private void dispatchUncaughtException(Throwable e) {
788         getUncaughtExceptionHandler().uncaughtException(this, e);
789     }
790 
791     static void processQueue(ReferenceQueue<Class<?>> queue,
792                              ConcurrentMap<? extends
793                                      WeakReference<Class<?>>, ?> map) {
794         Reference<? extends Class<?>> ref;
795         while ((ref = queue.poll()) != null) {
796             map.remove(ref);
797         }
798     }
799 
800     static class WeakClassKey extends WeakReference<Class<?>> {
801         private final int hash;
802 
803         WeakClassKey(Class<?> cl, ReferenceQueue<Class<?>> refQueue) {
804             super(cl, refQueue);
805             hash = System.identityHashCode(cl);
806         }
807 
808         @Override
809         public int hashCode() {
810             return hash;
811         }
812 
813         @Override
814         public boolean equals(Object obj) {
815             if (obj == this)
816                 return true;
817 
818             if (obj instanceof WeakClassKey) {
819                 Object referent = get();
820                 return (referent != null) &&
821                         (referent == ((WeakClassKey) obj).get());
822             } else {
823                 return false;
824             }
825         }
826     }
827 
828     @sun.misc.Contended("tlr")
829     long threadLocalRandomSeed;
830 
831     @sun.misc.Contended("tlr")
832     int threadLocalRandomProbe;
833 
834     @sun.misc.Contended("tlr")
835     int threadLocalRandomSecondarySeed;
836 
837     private native void setPriority0(int newPriority);
838 
839     private native void stop0(Object o);
840 
841     private native void suspend0();
842 
843     private native void resume0();
844 
845     private native void interrupt0();
846 
847     private native void setNativeName(String name);
848     
849 }

 

转载于:https://www.cnblogs.com/sakura1027/p/9204545.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值