前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一个线程start多次

一个线程start多次

作者头像
IT云清
发布2019-01-22 15:23:08
9930
发布2019-01-22 15:23:08
举报
文章被收录于专栏:IT云清IT云清
一个线程start多次会怎样?
结果:会报错。报错如下:
代码语言:javascript
复制
Exception in thread "main" java.lang.IllegalThreadStateException
    at java.lang.Thread.start(Thread.java:705)
    at com.java4all.test4.Test1.main(Test1.java:13)
分析:

看Thread类的源码,分析一下原因:

1.start方法的源码:
代码语言:javascript
复制
    /**
     * Causes this thread to begin execution; the Java Virtual Machine
     * calls the <code>run</code> method of this thread.
     * <p>
     * The result is that two threads are running concurrently: the
     * current thread (which returns from the call to the
     * <code>start</code> method) and the other thread (which executes its
     * <code>run</code> method).
     * <p>
     * It is never legal to start a thread more than once.
     * In particular, a thread may not be restarted once it has completed
     * execution.
        //一个线程启动超过一次,是不合法的。
        //特别的,一个线程一旦完成,就不会被重新start。
     *
     * @exception  IllegalThreadStateException  if the thread was already
     *               started.
        //如果一个线程已经启动了,再调用start方法,会抛出:IllegalThreadStateException异常。
     * @see        #run()
     * @see        #stop()
     */
     //同步方法
    public synchronized void start() {
        /**
         * This method is not invoked for the main method thread or "system"
         * group threads created/set up by the VM. Any new functionality added
         * to this method in the future may have to also be added to the VM.
         *
         * A zero status value corresponds to state "NEW".
            新线程的状态为0
         */
        if (threadStatus != 0)
            //如果线程状态不是0,会抛出IllegalThreadStateException异常。
            throw new IllegalThreadStateException();

        /* Notify the group that this thread is about to be started
         * so that it can be added to the group's list of threads
         * and the group's unstarted count can be decremented. */
         //通知线程组这个线程即将要start,所以可以让它加入线程组,并且,线程组中的未启动线程数将会减少一个。
        group.add(this);

        boolean started = false;
        try {
            start0();//这个方法时个本地方法,native方法
            started = true;//启动线程后设置标志位为true
        } finally {
            try {
                if (!started) {
                //如果标记为false,执行threadStartFailed方法,见下分析
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                /* do nothing. If start0 threw a Throwable then
                  it will be passed up the call stack */
            }
        }
    }
2.start0方法源码:
代码语言:javascript
复制
//这是一个native方法
    private native void start0();
下面几个方法是在ThreadGroup这个类中
1.threadStartFailed方法源码:
代码语言:javascript
复制
    /**
     * Notifies the group that the thread {@code t} has failed
     * an attempt to start.
     //通知线程组,这个线程启动失败
     *
     * <p> The state of this thread group is rolled back as if the
     * attempt to start the thread has never occurred. The thread is again
     * considered an unstarted member of the thread group, and a subsequent
     * attempt to start the thread is permitted.
     *
     //线程组的状态将会回滚到就像从未启动过此线程一样的状态。
     这个线程将会被当做未启动的线程存在于线程组中,并且允许后面的线程开始start
     * @param  t
     *         the Thread whose start method was invoked
     */
    void threadStartFailed(Thread t) {
        synchronized(this) {//同步方法
            remove(t);//从线程组中移除此线程
            nUnstartedThreads++;//未启动线程数+1
        }
    }
2.remove方法源码:
代码语言:javascript
复制
    /**
     * Removes the specified Thread from this group. Invoking this method
     * on a thread group that has been destroyed has no effect.
     //从线程组中移除指定线程,在已经被销毁的线程池中执行此方法是没有效果的。
     *
     * @param  t
     *         the Thread to be removed
     */
    private void remove(Thread t) {
        synchronized (this) {//同步
            if (destroyed) {
                return;
            }
            for (int i = 0 ; i < nthreads ; i++) {
                if (threads[i] == t) {
                    System.arraycopy(threads, i + 1, threads, i, --nthreads - i);
                    // Zap dangling reference to the dead thread so that
                    // the garbage collector will collect it.

                    //悬摆指针(不知道怎么翻译)指向这个死线程,这样垃圾回收机就可以回收这个了。
                    threads[nthreads] = null;
                    break;
                }
            }
        }
    }
3.add方法源码
代码语言:javascript
复制
    /**
     * Adds the specified thread to this thread group.
     //制定的线程添加到线程组中。
     *
     * <p> Note: This method is called from both library code
     * and the Virtual Machine. It is called from VM to add
     * certain system threads to the system thread group.
     *
     * @param  t
     *         the Thread to be added
     *
     * @throws  IllegalThreadStateException
     *          if the Thread group has been destroyed
     */
    void add(Thread t) {
        synchronized (this) {
            if (destroyed) {
            //如果线程组被销毁,会抛出IllegalThreadStateException错误
                throw new IllegalThreadStateException();
            }
            if (threads == null) {
            //线程组为null时,新建一个
                threads = new Thread[4];
            } else if (nthreads == threads.length) {
            //如果线程组的大小和线程数量相等,那就把线程组扩容到线程数量的2倍
                threads = Arrays.copyOf(threads, nthreads * 2);
            }
            //把此线程赋值到线程组中
            threads[nthreads] = t;

            // This is done last so it doesn't matter in case the
            // thread is killed
            //线程数量+1
            nthreads++;

            // The thread is now a fully fledged member of the group, even
            // though it may, or may not, have been started yet. It will prevent
            // the group from being destroyed so the unstarted Threads count is
            // decremented.
            //未start线程数量-1
            nUnstartedThreads--;
        }
    }

结论:同一个线程只能start一次,多次调用start方法会抛出异常。当调用start方法时,线程会被添加到线程组中,等待线程调度器调用,当获取到资源时,就进入运行状态。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018年08月15日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一个线程start多次会怎样?
  • 结果:会报错。报错如下:
  • 分析:
    • 1.start方法的源码:
      • 2.start0方法源码:
      • 下面几个方法是在ThreadGroup这个类中
        • 1.threadStartFailed方法源码:
          • 2.remove方法源码:
            • 3.add方法源码
            • 结论:同一个线程只能start一次,多次调用start方法会抛出异常。当调用start方法时,线程会被添加到线程组中,等待线程调度器调用,当获取到资源时,就进入运行状态。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档