线程的实现,调度和生命周期

前言

经常在面试的时候问到Java的线程生命周期,虽然实际运用中不会关注这些。但了解Java线程的实现,调度和生命周期,对编程就会豁然开朗。

1. 线程的实现

线程是比进程更轻量级的调度执行单位,线程的引入,可以把一个进程的资源和执行调度分开,各个线程既可以共享进程资源(内存地址、文件IO等),又可以独立调度,线程是CPU调度的基本单位

1.1 内核线程实现

直接由操作内核支持的线程,由内核完成线程的切换。

程序一般不会直接使用内核线程,而是使用内核线程的一种高级接口-轻量级进程。

局限性:需要系统调度,系统调度代价大,需要在用户态和内核态来回切换;内核进程数量有限。

1.2 用户线程实现

完全建立在用户空间的线程库上,系统内核无感知。JDK1.2之前使用这种模式。

优势:性能极强。用户线程的建立,同步,销毁和调度完全在用户态中完成,操作非常快,低消耗,无需切换内核态。

局限性:所有操作都需要自己实现,逻辑极其复杂。

1.3 用户线程和轻量级进程混合实现

用户线程负责创建,切换,析构等操作,而轻量级进程则负责用户线程和内核的交互,使用内核提供线程调度和处理器映射能力。JDK1.2开始支持。

2. Java线程的调度

就是对线程分配处理器的使用权

2.1. 协同式

一个线程干完活通知系统让另一个线程干活,实现简单;执行时间不受控制,一个线程阻塞,会直接阻塞整个进程。

2.2. 抢占式

系统分配线程的执行时间,受系统控制。

3. 线程状态

定义在Thread的内部枚举,Java线程总共有6种状态

/**
     * A thread state.  A thread can be in one of the following states:
     * <ul>
     * <li>{@link #NEW}<br>
     *     A thread that has not yet started is in this state.
     *     </li>
     * <li>{@link #RUNNABLE}<br>
     *     A thread executing in the Java virtual machine is in this state.
     *     </li>
     * <li>{@link #BLOCKED}<br>
     *     A thread that is blocked waiting for a monitor lock
     *     is in this state.
     *     </li>
     * <li>{@link #WAITING}<br>
     *     A thread that is waiting indefinitely for another thread to
     *     perform a particular action is in this state.
     *     </li>
     * <li>{@link #TIMED_WAITING}<br>
     *     A thread that is waiting for another thread to perform an action
     *     for up to a specified waiting time is in this state.
     *     </li>
     * <li>{@link #TERMINATED}<br>
     *     A thread that has exited is in this state.
     *     </li>
     * </ul>
     *
     * <p>
     * A thread can be in only one state at a given point in time.
     * These states are virtual machine states which do not reflect
     * any operating system thread states.
     *
     * @since   1.5
     * @see #getState
     */
    public enum State {
        /**
         * Thread state for a thread which has not yet started.
         */
        NEW,

        /**
         * Thread state for a runnable thread.  A thread in the runnable
         * state is executing in the Java virtual machine but it may
         * be waiting for other resources from the operating system
         * such as processor.
         */
        RUNNABLE,

        /**
         * Thread state for a thread blocked waiting for a monitor lock.
         * A thread in the blocked state is waiting for a monitor lock
         * to enter a synchronized block/method or
         * reenter a synchronized block/method after calling
         * {@link Object#wait() Object.wait}.
         */
        BLOCKED,

        /**
         * Thread state for a waiting thread.
         * A thread is in the waiting state due to calling one of the
         * following methods:
         * <ul>
         *   <li>{@link Object#wait() Object.wait} with no timeout</li>
         *   <li>{@link #join() Thread.join} with no timeout</li>
         *   <li>{@link LockSupport#park() LockSupport.park}</li>
         * </ul>
         *
         * <p>A thread in the waiting state is waiting for another thread to
         * perform a particular action.
         *
         * For example, a thread that has called <tt>Object.wait()</tt>
         * on an object is waiting for another thread to call
         * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
         * that object. A thread that has called <tt>Thread.join()</tt>
         * is waiting for a specified thread to terminate.
         */
        WAITING,

        /**
         * Thread state for a waiting thread with a specified waiting time.
         * A thread is in the timed waiting state due to calling one of
         * the following methods with a specified positive waiting time:
         * <ul>
         *   <li>{@link #sleep Thread.sleep}</li>
         *   <li>{@link Object#wait(long) Object.wait} with timeout</li>
         *   <li>{@link #join(long) Thread.join} with timeout</li>
         *   <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
         *   <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
         * </ul>
         */
        TIMED_WAITING,

        /**
         * Thread state for a terminated thread.
         * The thread has completed execution.
         */
        TERMINATED;
    }

状态的转换如图所示

3.1 新建(NEW)

创建后尚未启动的线程处于这个状态

这个时候从本质上仅是一个Thread对象。

3.2 运行(RUNNABLE)

Runnable包括了操作系统线程状态中的Running和Ready,也就是处于此状态的线程可能正在运行,也有可能正在等待CPU为它分配执行时间。

3.3 无限期等待(Waiting)

处于这种状态的线程不会被分配CPU执行时间,它们要等待被其它线程显示地唤醒。以下方法会让线程陷入无限期等待状态:

1)没有设置timeout参数的Object.wait()方法。

2)没有设置timeout参数的Thread.join()方法。

3)LockSupport.park()方法。

3.4 限期等待(Timed Waiting)

处于这种状态的线程也不会被分配CPU执行时间,不过无需等待被其它线程显示地唤醒,在一定时间之后它们会由系统自动的唤醒。以下方法会让线程进入TIMED_WAITING限期等待状态:

1)Thread.sleep()方法

2)设置了timeout参数的Object.wait()方法

3)设置了timeout参数的Thread.join()方法

4)LockSupport.parkNanos()方法

5)LockSupport.parkUntil()方法

3.5 阻塞(Blocked)

线程被阻塞了,说明一下和等待状态的区别

阻塞状态:在等待着获取到一个排他锁,这个事件在另外一个线程放弃这个锁的时候发生

等待状态:在等待一段时间,或者唤醒动作的发生。在程序等待进入同步区域的时候,线程将进入这种状态。

3.6 结束(Terminated)

已终止线程

4. 线程状态的获取

Thread对象提供如下方法支持

    /**
     * Returns the state of this thread.
     * This method is designed for use in monitoring of the system state,
     * not for synchronization control.
     *
     * @return this thread's state.
     * @since 1.5
     */
    public State getState() {
        // get current thread state
        return sun.misc.VM.toThreadState(threadStatus);
    }

5. jstack查看线程的状态

5.1 jps命令

jps

左边就是进程ID,俗称PID

5.2 查看进程下的线程

ps -mp pid -o THREAD, tid, time

虚拟机跑得,没部署应用,图中TID即是线程ID

5.3 16进制转换

printf "%x\n" 线程tid

5.4 生成Java栈日志

jstack 进程ID > 1.log

5.5 日志搜索

grep 16进制线程ID 1.log 

"TestThread" prio=10 tid=0x0000xxxxxxxxx nid=0x8e6 in Object.wait()
 
java.lang.Thread.State : RUNNABLE
 
       at xxx.xxx.xxx.class.xxxmethod(xx.java:xx行)

引用: JVM高级特性与最佳实践

猜你喜欢

转载自blog.csdn.net/fenglllle/article/details/83064635