zoukankan      html  css  js  c++  java
  • 从Thread.start()方法看Thread源码,多次start一个线程会怎么样

    这篇文章作为Thread类源码剖析的补充,从一个侧面来看Thread源码。也解答了面试高频问题:“多次start一个线程会怎么样?”

    答案是:java.lang.IllegalThreadStateException   线程状态非法异常   继承关系是:--->extends IllegalArgumentException--->extends RuntimeException一个运行时异常,下面我们从源码来透彻分析一下start()时做了什么。

     1 /**
     2      * Causes this thread to begin execution; the Java Virtual Machine
     3      * calls the <code>run</code> method of this thread.
     4      * <p>线程被执行,JVM调用run方法
     5      * The result is that two threads are running concurrently: the
     6      * current thread (which returns from the call to the
     7      * <code>start</code> method) and the other thread (which executes its
     8      * <code>run</code> method).
     9      * <p>
    10      * It is never legal to start a thread more than once.多次调用start方法启动一个线程是非法的
    11      * In particular, a thread may not be restarted once it has completed
    12      * execution.
    13      *
    14      * @exception  IllegalThreadStateException  if the thread was already已经启动的线程再次start,异常
    15      *               started.
    16      * @see        #run()
    17      * @see        #stop()
    18      */
    19     public synchronized void start() {
    20         /**
    21          * This method is not invoked for the main method thread or "system"
    22          * group threads created/set up by the VM. Any new functionality added
    23          * to this method in the future may have to also be added to the VM.
    24          *
    25          * A zero status value corresponds to state "NEW".
    26          */
    27         if (threadStatus != 0)//状态校验  0:NEW 新建状态
    28             throw new IllegalThreadStateException();
    29 
    30         /* Notify the group that this thread is about to be started
    31          * so that it can be added to the group's list of threads
    32          * and the group's unstarted count can be decremented. */
    33         group.add(this);//添加进线程组
    34 
    35         boolean started = false;
    36         try {
    37             start0();//调用native方法执行线程run方法
    38             started = true;
    39         } finally {
    40             try {
    41                 if (!started) {
    42                     group.threadStartFailed(this);//启动失败,从线程组中移除当前前程。
    43                 }
    44             } catch (Throwable ignore) {
    45                 /* do nothing. If start0 threw a Throwable then
    46                   it will be passed up the call stack */
    47             }
    48         }
    49     }
    50 
    51     private native void start0();

    greop.add(this),把当前线程添加进线程组,源码如下:

     1 /**
     2      * Adds the specified thread to this thread group.
     3      *
     4      * <p> Note: This method is called from both library code
     5      * and the Virtual Machine. It is called from VM to add
     6      * certain system threads to the system thread group.
     7      *
     8      * @param  t
     9      *         the Thread to be added
    10      *
    11      * @throws  IllegalThreadStateException
    12      *          if the Thread group has been destroyed
    13      */
    14     void add(Thread t) {
    15         synchronized (this) {
    16             if (destroyed) {//线程组状态校验
    17                 throw new IllegalThreadStateException();
    18             }
    19             if (threads == null) {
    20                 threads = new Thread[4];//初始化长度为4的Thread数组
    21             } else if (nthreads == threads.length) {//数组满了就扩容2倍
    22                 threads = Arrays.copyOf(threads, nthreads * 2);
    23             }
    24             threads[nthreads] = t;//新线程t添加进数组
    25 
    26             // This is done last so it doesn't matter in case the
    27             // thread is killed
    28             nthreads++;//线程数加1
    29 
    30             // The thread is now a fully fledged member of the group, even
    31             // though it may, or may not, have been started yet. It will prevent
    32             // the group from being destroyed so the unstarted Threads count is
    33             // decremented.
    34             nUnstartedThreads--;//未启动线程数-1
    35         }
    36     }

    启动失败后调用group.threadStartFailed(this),都是加锁方法,从线程组中移除当前线程,源码如下

     1 void threadStartFailed(Thread t) {
     2         synchronized(this) {
     3             remove(t);//移除线程t
     4             nUnstartedThreads++;//未启动线程+1
     5         }
     6     }
     7 
     8 private void remove(Thread t) {
     9         synchronized (this) {
    10             if (destroyed) {
    11                 return;
    12             }
    13             for (int i = 0 ; i < nthreads ; i++) {
    14                 if (threads[i] == t) {
    15                     System.arraycopy(threads, i + 1, threads, i, --nthreads - i);
    16                     // Zap dangling reference to the dead thread so that
    17                     // the garbage collector will collect it.
    18                     threads[nthreads] = null;
    19                     break;
    20                 }
    21             }
    22         }
    23     }
  • 相关阅读:
    实现多页签切换效果
    CSS样式display:none和visibility:hidden的区别
    canvas主要属性和方法
    Web前端的35个jQuery小技巧
    div+css3实现的小丸子和爷爷
    Jquery实现手机上下滑屏滑动的特效代码
    使用phantomjs生成网站快照
    VSCode配置Go language tools
    TypeScript中慎用forEach
    win8开发之数据绑定控件Gridview以分组及不同项模板的形式呈现数据
  • 原文地址:https://www.cnblogs.com/dennyzhangdd/p/7612194.html
Copyright © 2011-2022 走看看