Java多线程3-Thread简介

2018-07-17  本文已影响0人  唐影若凡

声明:原创文章,转载请注明出处。https://www.jianshu.com/p/4f9de47d1c43

一、线程生命周期

线程的状态有NEW、RUNNABLE、RUNNING、BLOCKED和TERMINATED五个状态。如下图所示:


Thread生命周期

二、start()和run()方法的区别

如下,我们新建一个线程,并执行start()方法,使其进入RUNNABLE状态。然而我们重写的run()方法却执行了,这是为什么?

public static void main(String[] args) {
    Thread t1 = new Thread() {
       @Override
        public void run() {
            System.out.println("hello world.");
        }
    };
    t1.start();
}

我们看下start()的源码:

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 */
            }
        }
    }

可以看到,start()方法的核心为:start0()方法。start0()为native方法。在线程执行时,start0()会调用run()方法。

结论1:启动线程,应该执行start()方法。如果调用run()方法,有时会看到相同的执行结果,但实际上只是执行了Thread对象的一个普通方法,并没有多线程运行。

结论2:从start()的源码可以看到,如果执行两次start(),会出现IllegalThreadStateException

结论3:如果一个线程的逻辑单元执行完,会进入TERMINATED状态,再次执行start()也是不行的。通过上一节的状态转换图看到,从TERMINATED状态并不能回到RUNNABLE状态。

三、sleep()和yield()方法的区别

四、join()方法

我们先从一个例子说起:

public class ThreadDemo {

    public static void main(String[] args) throws Exception {
        Thread t1 = new Thread() {
            @Override
            public void run() {
                System.out.println("t1 thread");
            }
        };

        Thread t2 = new Thread() {
            @Override
            public void run() {
                try {
                    t1.join();
                } catch (Exception e) {}
                System.out.println("t2 thread");
            }
        };

        t1.start();
        t2.start();
        t2.join();
        System.out.println("main thread");
    }
}
t1 thread
t2 thread
main thread

无论输出多次其结果都是固定的t1→t2→main。如果去掉join()方法,则三者的顺序则不固定。

当前线程Main执行中,join线程t2,则Main线程进入BLOCKED状态,直到t2结束生命周期或达到指定时间。同样地,t2线程执行中,join线程t1,则t2线程会等到t1线程执行完才会执行。

结论:当前执行线程join某个线程之后,该执行线程会等待join线程执行完/达到指定时间才会继续进行执行。常见的场景是一个任务分割成多个小任务,等各个小任务均执行完成后,再执行汇总操作。

上一篇 下一篇

猜你喜欢

热点阅读