从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 Machine3 * calls the <code>run</code> method of this thread.4 * <p>线程被执行,JVM调用run方法5 * The result is that two threads are running concurrently: the6 * current thread (which returns from the call to the7 * <code>start</code> method) and the other thread (which executes its8 * <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 code5 * and the Virtual Machine. It is called from VM to add6 * certain system threads to the system thread group.7 *8 * @param t9 * 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);//移除线程t4 nUnstartedThreads++;//未启动线程+15 }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 }
从Thread.start()方法看Thread源码,多次start一个线程会怎么样相关推荐
- 线程方法notify/notifyAll源码分析
众所周知,使用notify/notifyAll方法能唤醒wait等待的线程,那么在底层源码究竟做了些什么呢? 本章内容要解决的问题 问题1:notify/nofityAll真的唤醒了线程吗? 问题2: ...
- JDK源码解析 Runable是一个典型命令模式,Runnable担当命令的角色,Thread充当的是调用者,start方法就是其执行方法
JDK源码解析 Runnable是一个典型命令模式, Runnable担当命令的角色,Thread充当的是调用者,start方法就是其执行方法 /命令接口(抽象命令角色) public interfa ...
- 20种看asp源码的方法及工具
作者:欧杨飘雪 http://blog.csdn.net/flyingsnowy/ 众所周知windows平台漏洞百出,补丁一个接一个,但总是补也补不净.我把我所知道的20种看asp源码的方法总结了 ...
- 最近看Kafka源码,着实被它的客户端缓冲池技术优雅到了
最近看kafka源码,着实被它的客户端缓冲池技术优雅到了.忍不住要写篇文章赞美一下(哈哈). 注:本文用到的源码来自kafka2.2.2版本. 背景 当我们应用程序调用kafka客户端 produce ...
- Thread.yield()方法表示交出主动权,join表示等待当前线程,可以指定秒数
Thread.yield()方法表示交出主动权,join表示等待当前线程,可以指定秒数 学习了:http://www.importnew.com/14958.html 膜拜一下 源码膜拜: Threa ...
- 一点一点看JDK源码(五)java.util.ArrayList 后篇之forEach
一点一点看JDK源码(五)java.util.ArrayList 后篇之forEach liuyuhang原创,未经允许禁止转载 本文举例使用的是JDK8的API 目录:一点一点看JDK源码(〇) 代 ...
- 面试有没有看过spring源码_如何看Spring源码、Java每日六道面试分享,打卡第二天...
原标题:如何看Spring源码.Java每日六道面试分享,打卡第二天 想要深入的熟悉了解Spring源码,我觉得第一步就是要有一个能跑起来的极尽简单的框架,下面我就教大家搭建一个最简单的Spring框 ...
- 一点一点看JDK源码(四)java.util.ArrayList 中篇
一点一点看JDK源码(四)java.util.ArrayList 中篇 liuyuhang原创,未经允许禁止转载 本文举例使用的是JDK8的API 目录:一点一点看JDK源码(〇) 1.综述 在前篇中 ...
- 读取xml文件转成ListT对象的两种方法(附源码)
读取xml文件转成List<T>对象的两种方法(附源码) 读取xml文件,是项目中经常要用到的,所以就总结一下,最近项目中用到的读取xml文件并且转成List<T>对象的方法, ...
最新文章
- jquery即时搜索查询插件jquery.search.js
- redis安装过程中遇到的问题
- 使用 xcode 8 构建版本 iTunes Connect 获取不到应用程序的状态的解决办法
- 打造全能的文本编辑器序列文章
- Seleunim 获取文本和标签属性的方法
- Tensorflow:Tensorboard使用
- PHP中插件机制的一种实现方案
- Python Chainmap函数 - Python零基础入门教程
- 使用ffmpeg一行命令根据时间分割MP4文件
- mongodb安装及5安装studio 3t和studio3t破解
- html表格(table)的基本结构
- 芬兰建筑师帕特里克艾瑞克森先生一行访问云创
- Prometheus + Grafana 搭建监控报警系统
- 三角(Triangle)
- avalonia 控件TextBox 及其他控件文本改变事件
- docker部署html页面,在Docker容器中部署静态网页的方法教程
- zipJS 前端压缩使用
- 论文《Context Contrasted Feature and Gated Multi-scale Aggregation for Scene Segmentation》笔记
- 计算机无法检索文件夹,win7系统不能搜索文件夹怎么回事
- 互融云农产品追溯系统:区块链存证技术实现双向可追溯
热门文章
- 基于angular4+ng-bootstrap+bootstrap+scss的后台管理系统界面
- Angular js 具体应用(一)
- 百度地图与HT for Web结合的GIS网络拓扑应用
- Tomcat -- Cannot create a server using the sel...
- Deverpress 中国代理商使用 官方地址
- 企业网站服务器负载均衡技术
- 【机器学习】最近邻算法KNN原理、流程框图、代码实现及优缺点
- 一网打尽深度学习之卷积神经网络的经典网络(LeNet-5、AlexNet、ZFNet、VGG-16、GoogLeNet、ResNet)
- 语音信号的分帧加窗的matlab实现
- 数字图像处理实验(12):PROJECT 05-03,Periodic Noise Reduction Using a Notch Filter