测试代码: 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. 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()方法只是一个普通的方法。 |
|
来自: liang1234_ > 《java多线程》