zoukankan      html  css  js  c++  java
  • 同一个线程多次调用start()会出现的问题

    测试代码:

     1 package com.led.test;
     2 
     3 /**
     4  * @author Alan
     5  * @date 2018/6/18 15:09
     6  * @description 测试同一个线程多次调用start()方法
     7  */
     8 public class MuchStart implements Runnable{ //实现Runnable接口
     9     public void run() {
    10         System.out.println(Thread.currentThread().getName() + "is running ...");
    11     }
    12 
    13     public static void main(String[] args) {
    14         MuchStart muchStart = new MuchStart();
    15         Thread t = new Thread(muchStart);//创建实现了Runnable接口的Thread实例
    16         t.start();//多次调用start()方法
    17         t.start();
    18         t.start();
    19     }
    20 }

    测试结果:

      线程首先会运行一次,然后抛出java.lang.IllegalThreadStateException异常。

     接下来深入源码分析下原因:

      我们根据控制台的异常信息,定位到Thread.java的第708行,也就start()方法内部,打个断点调试:

       调试发现,第一个次运行start()方法时,threadStatus是0,此时if条件不满足,继续执行,会将当前线程添加到线程组中去执行。第二次运行start()方法时,threadStatus变成了2,if条件满足,于是抛出了java.lang.IllegalThreadStateException异常。

    Thread-0is running ...
    Exception in thread "main" java.lang.IllegalThreadStateException
        at java.lang.Thread.start(Thread.java:708)
        at com.led.test.MuchStart.main(MuchStart.java:17)

    start()源码进行分析

     1 /**
     2      * Causes this thread to begin execution; the Java Virtual Machine
     3      * calls the <code>run</code> method of this thread.
         让这个线程开始执行。JVM会调用这个线程的run()方法。
    4 * <p> 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 15 * started.
                  如果该线程已经启动,则再次调用start()方法,就会抛出IllegalThreadStateException异常。
    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)//新的线程threadState值是0 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);//通知线程组该线程将要开始运行,这样该线程就会被添加到线程列表中,此时列表的unstarted数将会减少。 34 35 boolean started = false; 36 try { 37 start0();//调用原生方法态方法启动线程 38 started = true;//已经运行的标记设置为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 }

    group.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) {//如果线程组的销毁标记(destroyed)是true,则抛出IllegalThreadStateException
    17                 throw new IllegalThreadStateException();
    18             }
    19             if (threads == null) {//如果线程数组为空,则初始为4个新的线程
    20                 threads = new Thread[4];
    21             } else if (nthreads == threads.length) {//如果当前线程组已满,则扩容至原来的2倍
    22                 threads = Arrays.copyOf(threads, nthreads * 2);
    23             }
    24             threads[nthreads] = 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     }

     start0()代码分析:

    1 private native void start0();//原生态代码,源码不在当前文件中,调用的其它文件的代码(可能是c/c++写的代码)

    threadStartFailed()源码分析:

     1 /**
     2      * Notifies the group that the thread {@code t} has failed
     3      * an attempt to start.
     4      * 通知线程组该线程尝试运行失败
     5      * <p> The state of this thread group is rolled back as if the
     6      * attempt to start the thread has never occurred. The thread is again
     7      * considered an unstarted member of the thread group, and a subsequent
     8      * attempt to start the thread is permitted.
     9      *
    10      * @param  t
    11      *         the Thread whose start method was invoked
    12      */
    13     void threadStartFailed(Thread t) {
    14         synchronized(this) {//同步
    15             remove(t);//从线程组中移除该线程
    16             nUnstartedThreads++;//未启动线程数+1
    17         }
    18     }

     总结:

      同一个线程只能调用start()方法一次,多次调用会抛出java.lang.IllegalThreadStateException。启动一个线程,需要调用start()方法而不是run()方法。此时,当前线程会被添加到线程组中,进入就绪状态,等待线程调度器的调用,若获取到了资源,则能进入运行状态,run()方法只是线程体,即线程执行的内容,若没调用start()方法,run()方法只是一个普通的方法。

  • 相关阅读:
    高效求解素数
    搭建redis集群
    搭建Spark高可用集群
    redis持久化
    elasticsearch简介
    java反射机制
    hdfs的客户端操作
    hdfs运行机制
    大数据概念
    hive
  • 原文地址:https://www.cnblogs.com/stm32stm32/p/9195318.html
Copyright © 2011-2022 走看看