一、前言

     主要分成两部说起:Thread源码解读和常见面试题解答,废话不多说开始;

二、源码解读

     首先看下构造函数,构造函数都是通过调用init方法对属性进行初始化,主要是对线程组、线程名字、栈大小等信息进行初始化;init内部通过调用currentThread本地方法,获取当前的线程,这个本地方法封装在JVM中,有兴趣的可以看下这个这个链接查找下JVM实现https://hg.openjdk.java.net/jdk8u,接下来对ThreadGroup的判断,如果没有传入线程组的话, 第一是使用SecurityManager中的ThreadGroup, 如果从SecurityManager 中获取不到ThreadGroup(), 那么就从当前线程中获取线程组,最后做了检验和些参数的赋值,整体上相对比较简单;

  1. private void init(ThreadGroup g, Runnable target, String name,
  2. long stackSize) {
  3. init(g, target, name, stackSize, null);
  4. }
  5. private void init(ThreadGroup g, Runnable target, String name,
  6. long stackSize, AccessControlContext acc) {
  7. if (name == null) {
  8. throw new NullPointerException("name cannot be null");
  9. }
  10. this.name = name.toCharArray();
  11. Thread parent = currentThread();
  12. SecurityManager security = System.getSecurityManager();
  13. if (g == null) {
  14. /* Determine if it's an applet or not */
  15. /* If there is a security manager, ask the security manager
  16. what to do. */
  17. if (security != null) {
  18. g = security.getThreadGroup();
  19. }
  20. /* If the security doesn't have a strong opinion of the matter
  21. use the parent thread group. */
  22. if (g == null) {
  23. g = parent.getThreadGroup();
  24. }
  25. }
  26. /* checkAccess regardless of whether or not threadgroup is
  27. explicitly passed in. */
  28. g.checkAccess();
  29. /*
  30. * Do we have the required permissions?
  31. */
  32. if (security != null) {
  33. if (isCCLOverridden(getClass())) {
  34. security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
  35. }
  36. }
  37. g.addUnstarted();
  38. this.group = g;
  39. this.daemon = parent.isDaemon();
  40. this.priority = parent.getPriority();
  41. if (security == null || isCCLOverridden(parent.getClass()))
  42. this.contextClassLoader = parent.getContextClassLoader();
  43. else
  44. this.contextClassLoader = parent.contextClassLoader;
  45. this.inheritedAccessControlContext =
  46. acc != null ? acc : AccessController.getContext();
  47. this.target = target;
  48. setPriority(priority);
  49. if (parent.inheritableThreadLocals != null)
  50. this.inheritableThreadLocals =
  51. ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
  52. /* Stash the specified stack size in case the VM cares */
  53. this.stackSize = stackSize;
  54. /* Set thread ID */
  55. tid = nextThreadID();
  56. }
  57. public Thread() {
  58. init(null, null, "Thread-" + nextThreadNum(), 0);
  59. }
  60. public Thread(Runnable target) {
  61. init(null, target, "Thread-" + nextThreadNum(), 0);
  62. }
  63. Thread(Runnable target, AccessControlContext acc) {
  64. init(null, target, "Thread-" + nextThreadNum(), 0, acc);
  65. }
  66. // 线程名
  67. public Thread(String name) {
  68. init(null, null, name, 0);
  69. }
  70. //线程组和线程名
  71. public Thread(ThreadGroup group, String name) {
  72. init(group, null, name, 0);
  73. }
  74. //线程任务,线程名
  75. public Thread(Runnable target, String name){
  76. init(null, target, name, 0);
  77. }
  78. // 线程组, 线程任务, 线程名 ,栈大小
  79. public Thread(ThreadGroup group, Runnable target, String name, long stackSize) {
  80. init(group, target, name, stackSize);
  81. }

View Code

      接下来看下主要的属性:

  1. // 类加载的时候,调用本地的注册本地方静态方法, 这个方法是本地方法
  2. private static native void registerNatives();
  3. static {
  4. registerNatives();
  5. }
  6. private volatile char name[];
  7. private int priority;
  8. private Thread threadQ;
  9. private long eetop;
  10. /* Whether or not to single_step this thread. */
  11. private boolean single_step;
  12. /* Whether or not the thread is a daemon thread. */
  13. // 设设置这个线程是否是守护线程
  14. private boolean daemon = false;
  15. /* JVM state */
  16. private boolean stillborn = false;
  17. /* What will be run. */
  18. // 要执行的run方法的对象
  19. private Runnable target;
  20. /* The group of this thread */
  21. // 这个线程的线程组
  22. private ThreadGroup group;
  23. /* The context ClassLoader for this thread */
  24. // 这个线程的上下文类加载器
  25. private ClassLoader contextClassLoader;
  26. /* The inherited AccessControlContext of this thread */
  27. private AccessControlContext inheritedAccessControlContext;
  28. /* For autonumbering anonymous threads. */
  29. private static int threadInitNumber;
  30. private static synchronized int nextThreadNum() {
  31. return threadInitNumber++;
  32. }
  33. /* ThreadLocal values pertaining to this thread. This map is maintained
  34. * by the ThreadLocal class. */
  35. ThreadLocal.ThreadLocalMap threadLocals = null;
  36. /*
  37. * InheritableThreadLocal values pertaining to this thread. This map is
  38. * maintained by the InheritableThreadLocal class.
  39. */
  40. ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
  41. /*
  42. * The requested stack size for this thread, or 0 if the creator did
  43. * not specify a stack size. It is up to the VM to do whatever it
  44. * likes with this number; some VMs will ignore it.
  45. */
  46. // 给这个线程设置的栈的大小,默认为0
  47. private long stackSize;
  48. /*
  49. * JVM-private state that persists after native thread termination.
  50. */
  51. private long nativeParkEventPointer;
  52. /*
  53. * Thread ID
  54. */
  55. //线程id
  56. private long tid;
  57. /* For generating thread ID */
  58. private static long threadSeqNumber;
  59. /* Java thread status for tools,
  60. * initialized to indicate thread 'not yet started'
  61. */
  62. private volatile int threadStatus = 0;
  63. private static synchronized long nextThreadID() {
  64. return ++threadSeqNumber;
  65. }
  66. /**
  67. * The argument supplied to the current call to
  68. * java.util.concurrent.locks.LockSupport.park.
  69. * Set by (private) java.util.concurrent.locks.LockSupport.setBlocker
  70. * Accessed using java.util.concurrent.locks.LockSupport.getBlocker
  71. */
  72. volatile Object parkBlocker;
  73. /* The object in which this thread is blocked in an interruptible I/O
  74. * operation, if any. The blocker's interrupt method should be invoked
  75. * after setting this thread's interrupt status.
  76. */
  77. private volatile Interruptible blocker;
  78. private final Object blockerLock = new Object();
  79. /* Set the blocker field; invoked via sun.misc.SharedSecrets from java.nio code
  80. */
  81. void blockedOn(Interruptible b) {
  82. synchronized (blockerLock) {
  83. blocker = b;
  84. }
  85. }
  86. /**
  87. * The minimum priority that a thread can have.
  88. */
  89. // 线程执行的最低优先级 为1
  90. public final static int MIN_PRIORITY = 1;
  91. /**
  92. * The default priority that is assigned to a thread.
  93. */
  94. // 线程默认的执行优先级为 5
  95. public final static int NORM_PRIORITY = 5;
  96. /**
  97. * The maximum priority that a thread can have.
  98. */
  99. // 线程执行的最高的优先级为 10
  100. public final static int MAX_PRIORITY = 10;

View Code

     最后介绍下方法的作用和线程状态,源码都比较简单,没必进行过多的介绍,都是通过调用JVM的本地方法实现;

     

    线程状态:

   

、常见面试题

    1.线程与进程的区别?

       进程是资源分配最小的单位,线程是CPU调度最小的单位;

       线程属于进程,共享进程分配的资源;

       进程属于抢占式调度,资源不相互共享;

    2.start和run的区别?

      run是Thread的一个普通的方法;

      start方法会创建一个新的子线程并启动;

    3.sleep与wait的区别?

      sleep是Thread方法,wait是Object的方法;

      wait方法只能在synchroized方法或者块中使用;

      Thread.sleep只会让出CPU,不会改变锁的行为;

      Object.wait不仅会让出CPU,同时还会释放占有同步资源的锁;

    4.线程状态的转化?

     图中将WAITING 和TIMED_WAITING 两个状态合并为WAITING ,没有分开,大家不要搞错;

    

 

 

     5.如何处理线程的返回值?

        主线程等待法,使用while等待主线程返回值;

        join阻塞当前线程以等待子线程;

        通过FuTureTask获取子线程的返回值;

  1. public class MyCallable implements Callable<String> {
  2. @Override
  3. public String call() throws Exception {
  4. String value="test";
  5. System.out.println("start");
  6. Thread.sleep(5000);
  7. System.out.println("end");
  8. return value;
  9. }
  10. }
  11. public class FutureTaskDemo {
  12. public static void main(String[] main) throws ExecutionException, InterruptedException {
  13. FutureTask<String> futureTask=new FutureTask<String>(new MyCallable());
  14. new Thread(futureTask).start();
  15. if (!futureTask.isDone()){
  16. System.out.println("waiting");
  17. }
  18. System.out.println("return"+futureTask.get());
  19. }
  20. }

View Code

        通过线程池获取返回值; 

  1. public class ThreadPoolDemo {
  2. public static void main(String[] args){
  3. ExecutorService executorService= Executors.newCachedThreadPool();
  4. Future<String> futureTask=executorService.submit(new MyCallable());
  5. if (!futureTask.isDone()){
  6. System.out.println("wait");
  7. }
  8. try {
  9. System.out.println(futureTask.get());
  10. }catch (InterruptedException ex){
  11. ex.printStackTrace();
  12. }catch (ExecutionException ex){
  13. ex.printStackTrace();
  14. }finally {
  15. executorService.shutdown();
  16. }
  17. }
  18. }

View Code

    6.Thread和Runnable?

       Thread是类,Runnable是接口,Thread是Runnable实现;

       类的继承单一原则,Runnable是更高层次的抽象;

 四、结束

  欢迎大家加群438836709!欢迎大家关注我!

     

版权声明:本文为wtzbk原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/wtzbk/p/11443271.html