美文网首页
Java线程系列——线程的启动

Java线程系列——线程的启动

作者: 禺沫 | 来源:发表于2020-02-21 21:28 被阅读0次

    一、start和run的比较

    先看一个简单的例子

    public class StartAndRunMethod {
        public static void main(String[] args) {
            Runnable runnable = () -> {
                System.out.println(Thread.currentThread().getName());
            };
            runnable.run();
            new Thread(runnable).start();
        }
    }
    

    运行结果如下:
    main
    Thread-0
    可见,运行run()方法还是在主线程中执行。并没有起到新启线程的目的。

    二、start方法具体作用

    那么运行start()方法,具体都做了什么呢?

    1. 通知JVM有空闲的时候启动新线程,等待线程调度器执行。不一定会马上执行,线程执行顺序也无法保证。
    2. start()方法会涉及到两个线程,主线程和子线程。子线程是需要先做一些准备工作才能运行的。比如,让自己处于就绪状态(获取到除了cpu以外的其他资源,比如设置了上下文,栈,线程状态,pc指向了程序运行的位置)。准备工作做完后,才会被JVM或者操作系统调度到运行状态,等待获取cpu资源,再到运行状态,运行run方法中的代码。可见,一个线程的执行,并不简单。

    三、start方法的使用注意:

    那么在调用start()方法时,应该注意些什么?

    public class CantStartTwice {
        public static void main(String[] args) {
            Thread thread = new Thread();
            thread.start();
            thread.start();
        }
    }
    

    比如不小心运行了两次start(),运行结果如下:

    Exception in thread "main" java.lang.IllegalThreadStateException
    at java.lang.Thread.start(Thread.java:705)
    at startthread.CantStartTwice.main(CantStartTwice.java:11)

    出现了非法的线程状态异常。
    其原因为,一旦开始执行就从最开始的new状态,到后续的状态,比如runnable状态。一旦线程执行完毕,就会变成终止状态,而终止状态永远不能返回回去,所以才会抛出这个异常。

    四、start源码解析

    在java.lang.Thread中,源码如下:

    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".
         */
        if (threadStatus != 0)
            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. */
        group.add(this);
    
        boolean started = false;
        try {
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                /* do nothing. If start0 threw a Throwable then
                  it will be passed up the call stack */
            }
        }
    }
    
    private native void start0();
    

    可知,start方法主要进行了如下逻辑:
    1.启动新线程检查线程状态
    2.加入线程组
    3.调用start0()

    相关文章

      网友评论

          本文标题:Java线程系列——线程的启动

          本文链接:https://www.haomeiwen.com/subject/vubhqhtx.html