从Thread.start()方法看Thread源码,多次start一个线程会怎么样
2023-09-11 14:19:37 时间
这篇文章作为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 }
相关文章
- IAR屏蔽警告的方法
- Asp.Net中用JS中操作cookie的方法(源码实例)
- MATLAB 数据分析方法(第2版)1.2 MATLAB基础概述
- 采用Java 8中Lambda表达式和默认方法的模板方法模式
- Oracle的KILL锁表及清除session方法
- C#中扩展StringBuilder支持链式方法
- 源码调试debug_info 的作用和使用方法
- 《机器学习与数据科学(基于R的统计学习方法)》——2.12 读取Twitter数据
- 《贝叶斯方法:概率编程与贝叶斯推断》——1.7习题
- ConcurrentHashMap源码解析_05 get、remove方法
- AQS源码探究_04 成员方法解析(释放锁、响应中断出队逻辑)
- 为Linux服务器设置静态IP的方法
- 印度初创公司开发了下一代区块链网络安全解决方法
- SwiftUI Swift基础之Swift 数组的多种方法(教程含源码)
- 使用扩展有效对齐 SwiftUI 内容,创建自定义 SwiftUI 方法以快速对齐项目并使您的代码看起来简洁明了(教程含源码)
- No.045<软考>《(高项)备考大全》【专项1】《案例分析 - 简介、方法、技巧、理论》
- Jsoncpp 使用方法大全
- PhpStorm配置SVN的完整方法
- 在CentOS 7上安装Node.js的4种方法(yum安装和源码安装)
- vue源码中的一些工具方法
- 【算法】验证码识别基础方法及源码(转)
- 【设计模式】单例设计模式的N中Java实现方法
- 数据库删除odoo数据模型的方法
- adodb.RecordSet的属性和方法
- Python类的定义、方法和属性使用
- eclipse 使用jetty调试时,加依赖工程的源码调试方法
- 原生js源码之bind方法,兼容性封装(IE8)
- 原生js源码之Object.keys()方法
- 曹工说Spring Boot源码(2)-- Bean Definition到底是什么,咱们对着接口,逐个方法讲解
- 解决Can‘t uninstall ‘docker‘. No files were found to uninstall.不能卸载方法