这篇文章作为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. }

从Thread.start()方法看Thread源码,多次start一个线程会怎么样的更多相关文章

  1. 一点一点看JDK源码(五)java.util.ArrayList 后篇之Spliterator多线程遍历

    一点一点看JDK源码(五)java.util.ArrayList 后篇之Spliterator多线程遍历 liuyuhang原创,未经允许禁止转载 本文举例使用的是JDK8的API 目录:一点一点看J ...

  2. java 集合与数组的互转方法,与源码分析

    前言 java数组与集合需要互相转换的场景非常多,但是运用不好还是容易抛出UnSupportedOperationException.下面讲解一下互转的方法,以及结合源码分异常产生的原因 集合转数组 ...

  3. Thread.yield()方法表示交出主动权,join表示等待当前线程,可以指定秒数

    Thread.yield()方法表示交出主动权,join表示等待当前线程,可以指定秒数 学习了:http://www.importnew.com/14958.html 膜拜一下 源码膜拜: Threa ...

  4. Java线程状态、线程start方法源码、多线程、Java线程池、如何停止一个线程

    下面将依次介绍: 1. 线程状态.Java线程状态和线程池状态 2. start方法源码 3. 什么是线程池? 4. 线程池的工作原理和使用线程池的好处 5. ThreadPoolExecutor中的 ...

  5. 【实习记】2014-08-15文档太少看着源码用cgicc+stl库之模板谓词函数对象

        总结1: 今天找到了昨天scanf的问题答案,scanf与printf一样的神奇而复杂,稍不留神,就会被坑.scanf函数在读入非空白符分割的多个字符串的解决方法是这个:/* 以 | 分割 * ...

  6. 读取xml文件转成List<T>对象的两种方法(附源码)

    读取xml文件转成List<T>对象的两种方法(附源码) 读取xml文件,是项目中经常要用到的,所以就总结一下,最近项目中用到的读取xml文件并且转成List<T>对象的方法, ...

  7. 一点一点看JDK源码(〇)

    一点一点看JDK源码(〇) liuyuhang原创,未经允许进制转载 写在前面: 几乎所有的大神都会强调看源码,也强调源码的重要性: 但是如何看源码,源码看什么?看了什么用?看了怎么用? 困扰很多人, ...

  8. 一点一点看JDK源码(一)Collection体系概览

    一点一点看JDK源码(一)Collection体系概览 liuyuhang原创,未经允许进制转载 本文举例使用的是JDK8的API 目录:一点一点看JDK源码(〇) 1.综述 Collection为集 ...

  9. 一点一点看JDK源码(二)java.util.List

    一点一点看JDK源码(二)java.util.List liuyuhang原创,未经允许进制转载 本文举例使用的是JDK8的API 目录:一点一点看JDK源码(〇) 1.综述 List译为表,一览表, ...

随机推荐

  1. 转每天一个linux命令(14):head 命令

    head 与 tail 就像它的名字一样的浅显易懂,它是用来显示开头或结尾某个数量的文字区块,head 用来显示档案的开头至标准输出中,而 tail 想当然尔就是看档案的结尾. 1.命令格式: hea ...

  2. Ubuntu14.04下搭建VPN服务 -pptp

    在Ubantu下采用PPTP搭建VPN,优点是配置简单快捷.本教程亲自测试,熟练了在新机器上5分钟搞定VPN. - - - - - - - - - - - - - - - - - - - - - - ...

  3. Linux下C/C++和lua交互-Table

    本来这些文章都是在我的个人网站www.zhangyi.studio,目前处在备案状态,暂时访问不了,所以搬到这边.  最近这两天需要弄清楚C++和lua间相互调用和数据传递,废话不多说,直接上过程. ...

  4. macaca web(4)

    米西米西滴,吃过中午饭来一篇,话说,上回书说道macaca 测试web(3),参数驱动来搞,那么有小伙本又来给雷子来需求, 登录模块能不能给我给重新封装一下吗, 我说干嘛封装,现在不挺好,于是乎,接着 ...

  5. C# 单例模式(Singleton Pattern)

    (新手写博客,主要是对自己学习的归纳总结.会对很多小细节详解.) 单例模式的定义: 确保一个类只有一个实例,并提供一个全局访问点. 首先实例大家应该都明白就是类生成对象的过程简单的就是String s ...

  6. 花生壳DDNS为何不支持LetsEncrypt申请

    Inspired by Let's Encrypt Community , thx to sahsanu, jsha, and orzorc. 开端 Lets Encrypt 是一款免费的网站 SSL ...

  7. React——state

    在React--组件中介绍过组件有两种定义方式:函数形式以及类形式.但是要想在组件中使用state,就必须使用类形式定义组件. 组件中的state是组件私有的,完全由组件自己控制. 使用类形式定义一个 ...

  8. 转: 【Java并发编程】之十八:第五篇中volatile意外问题的正确分析解答(含代码)

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/17382679 在<Java并发编程学习笔记之五:volatile变量修饰符-意料之外 ...

  9. CentOS7中将home迁移到/下的命令 CentOS7中将home迁移到/下的命令

    # mkdir -p /backup # cp -r /home/* /backup # umount /home #  df -hl # fdisk -l # lvremove /dev/cento ...

  10. 团队作业8——第二次项目冲刺(Bata版本)--第二天

    一.Daily Scrum Meeting照片 二.燃尽图 三.项目进展 学号 成员 贡献比 201421123001 廖婷婷 15% 201421123002 翁珊 17% 201421123004 ...