源码版本:jdk8

其中的部分论证和示例代码:Java_Concurrency


类声明:

Thread本身实现了Runnable接口

Runnable:任务,《java编程思想》中表示该命名不好,或许叫Task更好;

Thread:线程,执行任务的载体;

  1. public class Thread implements Runnable

**构造方法: **

构造时,可以指定线程组,线程运行任务Runnable对象,线程名和栈大小

线程的所有构造方法,都是通过init()实现

  1. /**
  2. * Thread的所有public构造方法传入的inheritThreadLocals均为true
  3. * 只有一个权限为default的构造方法传入为false
  4. * 所有的构造方法实现均是调用了该方法
  5. */
  6. private void init(ThreadGroup g, Runnable target, String name,
  7. long stackSize, AccessControlContext acc,
  8. boolean inheritThreadLocals) {
  9. // 构造方法中传入的线程名不能为null
  10. // 默认线程名:"Thread-" + nextThreadNum()
  11. if (name == null) {
  12. throw new NullPointerException("name cannot be null");
  13. }
  14. this.name = name;
  15. // 被创建出来的线程是创建线程的子线程
  16. Thread parent = currentThread();
  17. // 新建线程的线程组
  18. // 如果构造方法传入的线程组为null,则通过这个流程来决定其线程组,通常,新建线程的线程组为其创建线程的线程组
  19. SecurityManager security = System.getSecurityManager();
  20. if (g == null) {
  21. /* Determine if it's an applet or not */
  22. /* If there is a security manager, ask the security manager
  23. what to do. */
  24. if (security != null) {
  25. g = security.getThreadGroup();
  26. }
  27. /* If the security doesn't have a strong opinion of the matter
  28. use the parent thread group. */
  29. if (g == null) {
  30. g = parent.getThreadGroup();
  31. }
  32. }
  33. /* checkAccess regardless of whether or not threadgroup is
  34. explicitly passed in. */
  35. g.checkAccess();
  36. /*
  37. * Do we have the required permissions?
  38. */
  39. if (security != null) {
  40. if (isCCLOverridden(getClass())) {
  41. security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
  42. }
  43. }
  44. g.addUnstarted();
  45. this.group = g;
  46. // 子线程默认拥有父线程的优先级和daemon属性
  47. this.daemon = parent.isDaemon();
  48. this.priority = parent.getPriority();
  49. if (security == null || isCCLOverridden(parent.getClass()))
  50. this.contextClassLoader = parent.getContextClassLoader();
  51. else
  52. this.contextClassLoader = parent.contextClassLoader;
  53. this.inheritedAccessControlContext =
  54. acc != null ? acc : AccessController.getContext();
  55. this.target = target;
  56. setPriority(priority);
  57. if (inheritThreadLocals && parent.inheritableThreadLocals != null)
  58. this.inheritableThreadLocals =
  59. ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
  60. /* Stash the specified stack size in case the VM cares */
  61. this.stackSize = stackSize;
  62. // 产生新的tid并设置
  63. tid = nextThreadID();
  64. }
  65. public long getId() {
  66. return tid;
  67. }

上面的源码中有一个stackSize的参数,这个一般不会使用,其具体请参考javadoc.

默认线程名:"Thread-" + nextThreadNum():

  1. /* For autonumbering anonymous threads. */
  2. private static int threadInitNumber;
  3. // 同步方法,保证tid的唯一性和连续性
  4. private static synchronized int nextThreadNum() {
  5. return threadInitNumber++;
  6. }
  7. // 线程名可以被修改
  8. public final synchronized void setName(String name) {
  9. checkAccess();
  10. if (name == null) {
  11. throw new NullPointerException("name cannot be null");
  12. }
  13. this.name = name;
  14. if (threadStatus != 0) {
  15. setNativeName(name);
  16. }
  17. }
  18. public final String getName() {
  19. return name;
  20. }

ThreadGroup:

《java编程思想》有云:把ThreadGroup当做是一次不成功的尝试即可,不用理会

示例:ThreadGroupTest.java

  1. public final ThreadGroup getThreadGroup() {
  2. return group;
  3. }

Thread类默认的toString()中有使用其ThreadGroup:

  1. public String toString() {
  2. ThreadGroup group = getThreadGroup();
  3. if (group != null) {
  4. return "Thread[" + getName() + "," + getPriority() + "," + group.getName() + "]";
  5. } else {
  6. return "Thread[" + getName() + "," + getPriority() + "," + "" + "]";
  7. }
  8. }

守护线程:

具体参考:Java 守护线程概述

示例:Daemon.java

  1. /**
  2. * Marks this thread as either a {@linkplain #isDaemon daemon} thread
  3. * or a user thread. The Java Virtual Machine exits when the only
  4. * threads running are all daemon threads.
  5. * <p> This method must be invoked before the thread is started.
  6. */
  7. public final void setDaemon(boolean on) {
  8. checkAccess();
  9. // 只有在线程开始前设置才有效
  10. if (isAlive()) {
  11. throw new IllegalThreadStateException();
  12. }
  13. daemon = on;
  14. }
  15. public final boolean isDaemon() {
  16. return daemon;
  17. }
  1. // 返回当前线程是否还活着
  2. // start()后且还没有死亡的线程均视为活着的线程
  3. public final native boolean isAlive();

线程优先级和线程状态:

Java 线程状态与优先级相关的知识题目

示例:ThreadState.java

Priority.java

构造时如果不指定,默认线程优先级就是NORM_PRIORITY

  1. public final static int MIN_PRIORITY = 1;
  2. public final static int NORM_PRIORITY = 5;
  3. public final static int MAX_PRIORITY = 10;
  4. public final void setPriority(int newPriority) {
  5. ThreadGroup g;
  6. checkAccess();
  7. // 优先级范围 1~10
  8. if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
  9. throw new IllegalArgumentException();
  10. }
  11. if((g = getThreadGroup()) != null) {
  12. if (newPriority > g.getMaxPriority()) {
  13. newPriority = g.getMaxPriority();
  14. }
  15. // 设置优先级
  16. setPriority0(priority = newPriority);
  17. }
  18. }
  19. public final int getPriority() {
  20. return priority;
  21. }
  22. private native void setPriority0(int newPriority);
  23. /**
  24. * A thread state. A thread can be in one of the following states:
  25. * NEW:A thread that has not yet started is in this state.
  26. * RUNNABLE:A thread executing in the Java virtual machine is in this state.
  27. * BLOCKED:A thread that is blocked waiting for a monitor lock is in this state.
  28. * WAITING:A thread that is waiting indefinitely for another thread to
  29. * perform a particular action is in this state.
  30. * TIMED_WAITING:A thread that is waiting for another thread to perform an action
  31. * for up to a specified waiting time is in this state.
  32. * TERMINATED:A thread that has exited is in this state.
  33. * A thread can be in only one state at a given point in time.
  34. * These states are virtual machine states which do not reflect
  35. * any operating system thread states.
  36. * @since 1.5
  37. */
  38. public enum State {
  39. // 创建后,但是没有start(),调用了start()后,线程才算准备就绪,可以运行(RUNNABLE)
  40. NEW,
  41. // 正在运行或正在等待操作系统调度
  42. RUNNABLE,
  43. // 线程正在等待监视器锁
  44. // 正在synchronized块/方法上等待获取锁,或者调用了Object.wait(),等待重新获得锁进入同步块
  45. BLOCKED,
  46. // 调用Object.wait(),Thread.join()或LockSupport.park()会进入该状态,注意这里的调用均为没有设置超时,
  47. // 线程正在等待其他线程进行特定操作,比如,调用了Object.wait()的线程在另一个线程调用Object.notify()/Object.notifyAll()
  48. // 调用了Thread.join()的线程在等待指定线程停止,join()的内部实现方式也是Object.wait(),只不过其Object就是线程对象本身
  49. WAITING,
  50. // 调用Thread.sleep(),Object.wait(long),Thread.join(long),
  51. // LockSupport.parkNanos(long),LockSupport.parkUntil(long)会进入该状态,
  52. // 注意,这里的调用均设置了超时
  53. TIMED_WAITING,
  54. // 线程执行完成,退出
  55. TERMINATED;
  56. }
  57. // @since 1.5
  58. public State getState() {
  59. // get current thread state
  60. return sun.misc.VM.toThreadState(threadStatus);
  61. }

这里关于线程状态需要特别注意,在网上有很多博客和书籍对线程状态进行讲解,其中很大一部分是错误的,对于BLOCKED,WAITING和TIMED_WAITING有所误解,认为一个线程在被从Object.wait()中被唤醒时,会立即进入Runnable状态,其实不是的:

一个线程在被从Object.wait()中被唤醒时,会立即进入BLOCKED状态,这时其并没有获得锁,只是被唤醒了,再次开始对Object的监视器锁进行竞争;只有在其竞争获得锁之后才会进入RUNNABLE状态.

在理解java线程状态时,建议直接看Thread.State的注释,就看英文版本,最贴切,没有杂质,也最正确,其他的所有书上的讲解似乎都有些偏颇

线程状态示例:ThreadState.java

线程优先级示例:Priority.java

关于wait()/notify()具体相关,请参考其他相关博客;

run():

如果是构造Thread对象的时候,传入了该对象预期执行的任务----Runnable对象时,执行该任务,否则,什么都不做,当然,可以通过集成Thread类,重写run(),来修改其行为:

  1. /* What will be run. */
  2. private Runnable target;
  3. @Override
  4. public void run() {
  5. if (target != null) {
  6. target.run();
  7. }
  8. }

线程启动:

调用start()与调用run()的区别:懒得说

  1. /* Java thread status for tools,
  2. * initialized to indicate thread 'not yet started'
  3. */
  4. private volatile int threadStatus = 0;
  5. // 启动线程,JVM会调用当前Thread对象的run()
  6. // 同步方法
  7. public synchronized void start() {
  8. // A zero status value corresponds to state "NEW".
  9. // 如果调用时不是在线程状态不是NEW,则抛出IllegalThreadStateException
  10. if (threadStatus != 0)
  11. throw new IllegalThreadStateException();
  12. /* Notify the group that this thread is about to be started
  13. * so that it can be added to the group's list of threads
  14. * and the group's unstarted count can be decremented. */
  15. group.add(this);
  16. boolean started = false;
  17. try {
  18. // 通过start0()来实现线程启动
  19. start0();
  20. started = true;
  21. } finally {
  22. try {
  23. if (!started) {
  24. group.threadStartFailed(this);
  25. }
  26. } catch (Throwable ignore) {
  27. /* do nothing. If start0 threw a Throwable then
  28. it will be passed up the call stack */
  29. }
  30. }
  31. }
  32. private native void start0();

线程打断:

示例:Interrupted.java

  1. /* The object in which this thread is blocked in an interruptible I/O
  2. * operation, if any. The blocker's interrupt method should be invoked
  3. * after setting this thread's interrupt status.
  4. */
  5. private volatile Interruptible blocker;
  6. private final Object blockerLock = new Object();
  7. /* Set the blocker field; invoked via sun.misc.SharedSecrets from java.nio code
  8. */
  9. void blockedOn(Interruptible b) {
  10. synchronized (blockerLock) {
  11. blocker = b;
  12. }
  13. }
  14. /**
  15. * 打断当前执行线程
  16. * 如果当前线程阻塞在Object.wait(),Thread.join(),Thread.sleep()上,
  17. * 那么该线程会收到InterruptedException,且线程的打断标志会被清除;
  18. * 如果当前线程阻塞在InterruptibleChannel上,那么该InterruptibleChannel
  19. * 会被关闭,线程的打断标志会被置位,且当前线程会收到ClosedByInterruptException;
  20. * 如果当前线程阻塞在Selector上,那么该Selector的selection操作将会立即返回一个非0的结果,
  21. * 且Selector.wakeup()会被调用,线程的打断标志会被置位,
  22. * 如果上述情况均不存在,将当前线程的打断标志置位
  23. * 打断一个isAlive()返回false的线程没有效果,isInterrupted()仍然会返回false;
  24. */
  25. public void interrupt() {
  26. if (this != Thread.currentThread())
  27. checkAccess();
  28. synchronized (blockerLock) {
  29. Interruptible b = blocker;
  30. // 在Interruptible上阻塞
  31. if (b != null) {
  32. interrupt0(); // Just to set the interrupt flag
  33. b.interrupt(this);
  34. return;
  35. }
  36. }
  37. interrupt0();
  38. }
  39. private native void interrupt0();
  40. /**
  41. * 返回线程是否被打断(打断标志是否被置位)
  42. * 传入的参数决定是否该方法是否会清除终端标志位
  43. */
  44. private native boolean isInterrupted(boolean ClearInterrupted);
  45. public static boolean interrupted() {
  46. return currentThread().isInterrupted(true);
  47. }
  48. public boolean isInterrupted() {
  49. return isInterrupted(false);
  50. }

关于isInterrupted()和interrupted()的区别,上述源码表现得很明显

而且,也体现了NIO的可中断中断实现方式

注意:interrupt()不能中断执行阻塞IO操作的线程.

线程的礼让—— yield() sleep() join():

关于Thread.sleep()和Object.wait()的区别:参考链接

示例:Yield.java

Join.java

  1. /**
  2. * 暗示调度器让出当前线程的执行时间片,调度器可以选择忽略该暗示;
  3. * 该方法在用来调试和测试时可能很有用,可以用来重现需要特殊条件才能复现的bug;
  4. * 也可以用来进行并发优化等;
  5. */
  6. public static native void yield();
  7. /**
  8. * 当前执行线程休眠指定毫秒在休眠期间,不释放任何当前线程持有的锁;
  9. */
  10. public static native void sleep(long millis) throws InterruptedException;
  11. /**
  12. * 当前执行线程休眠指定毫秒在休眠期间,不释放任何当前线程持有的锁;
  13. * 如果当前被打断(该方法调用前或该方法调用时),抛出InterruptedException,同时将打断标志清掉
  14. */
  15. public static void sleep(long millis, int nanos) throws InterruptedException {
  16. // 取值范围检查
  17. if (millis < 0) {
  18. throw new IllegalArgumentException("timeout value is negative");
  19. }
  20. if (nanos < 0 || nanos > 999999) {
  21. throw new IllegalArgumentException(
  22. "nanosecond timeout value out of range");
  23. }
  24. // 纳秒最后还是转换成了毫秒233333
  25. // 可能是考虑都有些
  26. if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
  27. millis++;
  28. }
  29. sleep(millis);
  30. }
  31. /**
  32. * 当前执行线程等待指定线程(也就是该调用发生的Thread对象)死后再继续执行;
  33. * 可以设置超时,如果设置超时为0,则为不设置超时;
  34. * 线程结束时(terminate),将会调用自身的notifyAll(),唤醒在该Thread对象上wait()的方法;
  35. * 如果该线程被打断,该方法将抛出InterruptedException,并将打断标志位清除
  36. */
  37. // 同步方法,同步当前Thread对象,所以才能在其内部调用wait()
  38. public final synchronized void join(long millis)
  39. throws InterruptedException {
  40. long base = System.currentTimeMillis();
  41. long now = 0;
  42. if (millis < 0) {
  43. throw new IllegalArgumentException("timeout value is negative");
  44. }
  45. // 使用isAlive()和wait()的循环实现
  46. if (millis == 0) {
  47. while (isAlive()) {
  48. wait(0);
  49. }
  50. } else {
  51. while (isAlive()) {
  52. long delay = millis - now;
  53. if (delay <= 0) {
  54. break;
  55. }
  56. wait(delay);
  57. now = System.currentTimeMillis() - base;
  58. }
  59. }
  60. }
  61. public final synchronized void join(long millis, int nanos)
  62. throws InterruptedException {
  63. if (millis < 0) {
  64. throw new IllegalArgumentException("timeout value is negative");
  65. }
  66. if (nanos < 0 || nanos > 999999) {
  67. throw new IllegalArgumentException(
  68. "nanosecond timeout value out of range");
  69. }
  70. if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
  71. millis++;
  72. }
  73. join(millis);
  74. }
  75. public final void join() throws InterruptedException {
  76. join(0);
  77. }
  78. /**
  79. * This method is called by the system to give a Thread
  80. * a chance to clean up before it actually exits.
  81. */
  82. private void exit() {
  83. if (group != null) {
  84. group.threadTerminated(this);
  85. group = null;
  86. }
  87. /* Aggressively null out all reference fields: see bug 4006245 */
  88. target = null;
  89. /* Speed the release of some of these resources */
  90. threadLocals = null;
  91. inheritableThreadLocals = null;
  92. inheritedAccessControlContext = null;
  93. blocker = null;
  94. uncaughtExceptionHandler = null;
  95. }

被遗弃的方法——suspend() resume() stop():

示例:Deprecated.java

关于这些方法被遗弃的原因,具体参考:Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?

  1. /**
  2. * 挂起当前线程
  3. * 弃用原因:容易导致死锁
  4. */
  5. @Deprecated
  6. public final void suspend() {
  7. checkAccess();
  8. suspend0();
  9. }
  10. /**
  11. * 从suspend()中恢复线程运行
  12. * 弃用原因:容易导致死锁
  13. */
  14. @Deprecated
  15. public final void resume() {
  16. checkAccess();
  17. resume0();
  18. }
  19. /**
  20. * 强制线程停止执行;
  21. * 通过抛出一个ThreadDeath的方式来停止线程;
  22. * 废弃原因:stop()会师范所有已持有的锁的监视器,如果存在之前被这些监视器保护的对象处于一个不连续
  23. * 的状态(inconsistent state),这些被损坏的对象将会对其他线程可见,出现不可预期的行为;
  24. */
  25. @Deprecated
  26. public final void stop() {
  27. SecurityManager security = System.getSecurityManager();
  28. if (security != null) {
  29. checkAccess();
  30. if (this != Thread.currentThread()) {
  31. security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION);
  32. }
  33. }
  34. // A zero status value corresponds to "NEW", it can't change to
  35. // not-NEW because we hold the lock.
  36. if (threadStatus != 0) {
  37. resume(); // Wake up thread if it was suspended; no-op otherwise
  38. }
  39. // The VM can handle all thread states
  40. stop0(new ThreadDeath());
  41. }

ThreadLocal:

在Thread类中有两个与ThreadLocal相关的成员变量

具体有关ThreadLocal,请参考:

一个故事讲明白线程的私家领地:ThreadLocal

ThreadLocal源码解读

  1. /* ThreadLocal values pertaining to this thread. This map is maintained
  2. * by the ThreadLocal class. */
  3. ThreadLocal.ThreadLocalMap threadLocals = null;
  4. /*
  5. * InheritableThreadLocal values pertaining to this thread. This map is
  6. * maintained by the InheritableThreadLocal class.
  7. */
  8. ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;

ClassLoader:

关于ClassLoader,我暂时知道的也不多,先知道这个,以后有机会专门研究一下ClassLoader:

  1. /* The context ClassLoader for this thread */
  2. private ClassLoader contextClassLoader;
  3. /**
  4. * 当前线程的ClassLoader,默认创建时是父线程的ClassLoader
  5. * @return the context ClassLoader for this Thread, or {@code null}
  6. * indicating the system class loader (or, failing that, the
  7. * bootstrap class loader)
  8. * @since 1.2
  9. */
  10. @CallerSensitive
  11. public ClassLoader getContextClassLoader() {
  12. if (contextClassLoader == null)
  13. return null;
  14. SecurityManager sm = System.getSecurityManager();
  15. if (sm != null) {
  16. ClassLoader.checkClassLoaderPermission(contextClassLoader,Reflection.getCallerClass());
  17. }
  18. return contextClassLoader;
  19. }
  20. /**
  21. * @param cl
  22. * the context ClassLoader for this Thread, or null indicating the
  23. * system class loader (or, failing that, the bootstrap class loader)
  24. * @since 1.2
  25. */
  26. public void setContextClassLoader(ClassLoader cl) {
  27. SecurityManager sm = System.getSecurityManager();
  28. if (sm != null) {
  29. sm.checkPermission(new RuntimePermission("setContextClassLoader"));
  30. }
  31. contextClassLoader = cl;
  32. }

线程栈轨迹:

  1. // 特殊编程技巧
  2. private static final StackTraceElement[] EMPTY_STACK_TRACE
  3. = new StackTraceElement[0];
  4. private native static StackTraceElement[][] dumpThreads(Thread[] threads);
  5. private native static Thread[] getThreads();
  6. // 打印当前线程的栈轨迹(StackTrace),通过新建一个异常的方式实现
  7. // 注意:这是一个静态方法
  8. public static void dumpStack() {
  9. new Exception("Stack trace").printStackTrace();
  10. }
  11. /**
  12. * 获得栈轨迹,返回的是一个数组
  13. * 数组的第0个栈轨迹为最近调用的栈轨迹
  14. * @since 1.5
  15. */
  16. public StackTraceElement[] getStackTrace() {
  17. if (this != Thread.currentThread()) {
  18. // check for getStackTrace permission
  19. SecurityManager security = System.getSecurityManager();
  20. if (security != null) {
  21. security.checkPermission(SecurityConstants.GET_STACK_TRACE_PERMISSION);
  22. }
  23. // 不是活着的,返回的栈轨迹长度为0
  24. if (!isAlive()) {
  25. return EMPTY_STACK_TRACE;
  26. }
  27. StackTraceElement[][] stackTraceArray = dumpThreads(new Thread[] {this});
  28. StackTraceElement[] stackTrace = stackTraceArray[0];
  29. // a thread that was alive during the previous isAlive call may have
  30. // since terminated, therefore not having a stacktrace.
  31. if (stackTrace == null) {
  32. // 这样就不会返回null,调用者也无需判断null了
  33. stackTrace = EMPTY_STACK_TRACE;
  34. }
  35. return stackTrace;
  36. } else {
  37. // Don't need JVM help for current thread
  38. return (new Exception()).getStackTrace();
  39. }
  40. }
  41. /**
  42. * 返回所有线程的栈轨迹
  43. * @since 1.5
  44. */
  45. public static Map<Thread, StackTraceElement[]> getAllStackTraces() {
  46. // check for getStackTrace permission
  47. SecurityManager security = System.getSecurityManager();
  48. if (security != null) {
  49. security.checkPermission(
  50. SecurityConstants.GET_STACK_TRACE_PERMISSION);
  51. security.checkPermission(
  52. SecurityConstants.MODIFY_THREADGROUP_PERMISSION);
  53. }
  54. // Get a snapshot of the list of all threads
  55. Thread[] threads = getThreads();
  56. StackTraceElement[][] traces = dumpThreads(threads);
  57. Map<Thread, StackTraceElement[]> m = new HashMap<>(threads.length);
  58. for (int i = 0; i < threads.length; i++) {
  59. StackTraceElement[] stackTrace = traces[i];
  60. if (stackTrace != null) {
  61. m.put(threads[i], stackTrace);
  62. }
  63. // else terminated so we don't put it in the map
  64. }
  65. return m;
  66. }

UncaughtExceptionHandler:

示例:UncaughtExceptionHandlerEx.java

  1. // null unless explicitly set
  2. private volatile UncaughtExceptionHandler uncaughtExceptionHandler;
  3. // null unless explicitly set
  4. private static volatile UncaughtExceptionHandler defaultUncaughtExceptionHandler;
  5. /**
  6. * 设置UncaughtExceptionHandler,该设置对所有线程有效
  7. * 如果自身没有设置,则交给其线程组的UncaughtExceptionHandler处理,如果再没有,
  8. * 则交给默认的的UncaughtExceptionHandler处理,也即这里设置的UncaughtExceptionHandler处理
  9. * 注意这里的设置不应该设置为线程的线程组,这样的设置会造成死循环
  10. * @since 1.5
  11. */
  12. public static void setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
  13. SecurityManager sm = System.getSecurityManager();
  14. if (sm != null) {
  15. sm.checkPermission(new RuntimePermission("setDefaultUncaughtExceptionHandler"));
  16. }
  17. defaultUncaughtExceptionHandler = eh;
  18. }
  19. /**
  20. * 返回默认的UncaughtExceptionHandler,该UncaughtExceptionHandler对所有线程有效
  21. * 这是一个静态方法
  22. * @since 1.5
  23. */
  24. public static UncaughtExceptionHandler getDefaultUncaughtExceptionHandler(){
  25. return defaultUncaughtExceptionHandler;
  26. }
  27. /**
  28. * 返回该线程的UncaughtExceptionHandler,如果没有,返回该线程的线程组
  29. * ThreadGroup本身实现了UncaughtExceptionHandler接口
  30. * @since 1.5
  31. */
  32. public UncaughtExceptionHandler getUncaughtExceptionHandler() {
  33. return uncaughtExceptionHandler != null ?
  34. uncaughtExceptionHandler : group;
  35. }
  36. /**
  37. * 设置该线程的UncaughtExceptionHandler
  38. */
  39. public void setUncaughtExceptionHandler(UncaughtExceptionHandler eh) {
  40. checkAccess();
  41. uncaughtExceptionHandler = eh;
  42. }
  43. /**
  44. * uncaught exception 分发给UncaughtExceptionHandler
  45. * 该方法被JVM调用
  46. */
  47. private void dispatchUncaughtException(Throwable e) {
  48. getUncaughtExceptionHandler().uncaughtException(this, e);
  49. }

其他:

  1. // 返回当前语句执行的线程
  2. public static native Thread currentThread();
  3. // 不能克隆线程
  4. @Override
  5. protected Object clone() throws CloneNotSupportedException {
  6. throw new CloneNotSupportedException();
  7. }
  8. /**
  9. * 返回该线程是否持有指定对象的监视器锁
  10. * @since 1.4
  11. */
  12. public static native boolean holdsLock(Object obj);

Thread类源码解析的更多相关文章

  1. Thread类源码剖析

    目录 1.引子 2.JVM线程状态 3.Thread常用方法 4.拓展点 一.引子 说来也有些汗颜,搞了几年java,忽然发现竟然没拜读过java.lang.Thread类源码,这次特地拿出来晒一晒. ...

  2. java.lang.Void类源码解析_java - JAVA

    文章来源:嗨学网 敏而好学论坛www.piaodoo.com 欢迎大家相互学习 在一次源码查看ThreadGroup的时候,看到一段代码,为以下: /* * @throws NullPointerEx ...

  3. Java集合---Array类源码解析

    Java集合---Array类源码解析              ---转自:牛奶.不加糖 一.Arrays.sort()数组排序 Java Arrays中提供了对所有类型的排序.其中主要分为Prim ...

  4. Java集合---Arrays类源码解析

    一.Arrays.sort()数组排序 Java Arrays中提供了对所有类型的排序.其中主要分为Primitive(8种基本类型)和Object两大类. 基本类型:采用调优的快速排序: 对象类型: ...

  5. ArrayList类源码解析——ArrayList动态数组的实现细节(基于JDK8)

    一.基本概念 ArrayList是一个可以添加对象元素,并进行元素的修改查询删除等操作的容器类.ArrayList底层是由数组实现的,所以和数组一样可以根据索引对容器对象所包含的元素进行快速随机的查询 ...

  6. Dom4j工具类源码解析

    话不多说,上源码: package com.changeyd.utils;import java.io.File;import java.io.FileNotFoundException;import ...

  7. Spring-IOC MethodInvokingFactoryBean 类源码解析

    MethodInvokingFactoryBean MethodInvokingFactoryBean的作用是,通过定义类和它的方法,然后生成的bean是这个方法的返回值,即可以注入方法返回值. Me ...

  8. 机器学习:weka中Evaluation类源码解析及输出AUC及交叉验证介绍

    在机器学习分类结果的评估中,ROC曲线下的面积AOC是一个非常重要的指标.下面是调用weka类,输出AOC的源码: try { // 1.读入数据集 Instances data = new Inst ...

  9. 23.mixin类源码解析

    mixin类用于提供视图的基本操作行为,注意mixin类提供动作方法,而不是直接定义处理程序方法 例如.get() .post(),这允许更灵活的定义,mixin从rest_framework.mix ...

随机推荐

  1. vue 学习笔记(二)

    最近公司赶项目,一直也没时间看 vue,之前看下的都快忘得差不多了.哈哈哈,来一起回顾一下vue 学习笔记(一)后,继续向下看嘛. #表单输入绑定 基础用法 v-model 会忽略所有表单元素的 va ...

  2. Linux 搭建批量网络装机

  3. CSS之不常用但重要的样式总结

    1,设置颜色渐变 background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.67), rgba(255, 255, 255, 0));( ...

  4. react初探(一)之JSX、状态(state)管理、条件渲染、事件处理

    前言: 最近收到组长通知我们项目组后面新开的项目准备统一技术栈为react,目前我的情况是三大框架只会angular和Vue.在实际项目中只使用过一次angular5,其余项目都是使用Vue写的.写篇 ...

  5. 在action中进行文件下载,下载时运行不报错,可是也不下载

    在写前端下载页面时,使用ajax方式调用action中的方法,然后就将下载内容返回js中了,所以没有下载,之后改为使用Windows.location进行下载,就没有问题了. action中代码: i ...

  6. springboot缓存注解——@Cacheable和@CacheConfig

    @Caching :制定多个缓存规则 @Cacheable 和 @CachePut 同时标注时 ,@CachePut导致还是会走方法跟数据库交互 //根据lastName查,并将结果缓存,并且可以用于 ...

  7. 雷林鹏分享:jQuery EasyUI 数据网格 - 创建列组合

    jQuery EasyUI 数据网格 - 创建列组合 easyui 的数据网格(DataGrid)可以创建列组合,如下所示: 在本实例中,我们使用平面数据来填充数据网格(DataGrid)的数据,并把 ...

  8. Java并发编程的艺术· 笔记(1)

    目录 1.volatile的原理 2.Synchonized 3.无锁-偏向锁-轻量级锁-重量级锁 4.Java实现原子操作 1.volatile的原理 如何保持可见性: 1)将当前处理器缓存行的数据 ...

  9. jquary高级和ajax

    jquary高级: 1.动画 1.三种方式显示与隐藏元素 1.默认显示和隐藏的方式 1.show([speed],[easing],[fn]):显示 [speed],[easing],[fn] spe ...

  10. 【HDU - 1429】胜利大逃亡(续) (高级搜索)【状态压缩+BFS】

    Ignatius再次被魔王抓走了(搞不懂他咋这么讨魔王喜欢)…… 这次魔王汲取了上次的教训,把Ignatius关在一个n*m的地牢里,并在地牢的某些地方安装了带锁的门,钥匙藏在地牢另外的某些地方.刚开 ...