只会一点java

java持续学习者,每月一篇博客。罗列出技术栈,慢慢完善,持续学习,总有一天,你会追上甚至超越曾经的大神。
  博客园  :: 首页  :: 联系 :: 订阅 订阅  :: 管理

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