美文网首页
线程的生命周期

线程的生命周期

作者: felixu | 来源:发表于2019-01-11 16:30 被阅读0次

    前面介绍了线程相关的一些基本概念,也说了一个线程的创建以及销毁,那么一个线程应该是有生命周期的。这里就来看一下,一个线程一生可能会经历哪些阶段。

    线程的六种状态

    线程的一生可能会经过以下6种状态:

    • NEW

      初始化状态,线程被创建,但是还没有调用start方法。

      线程的创建过程其实在前面从线程说起并发问题介绍线程创建的时候已经说过了,这里就不再上代码了,简单说一下使用线程的三种方式:

      • 实现Runnable接口,重写run方法。
      • 继承Thread类,重写run方法。
      • 实现Callable接口,重写call方法,实现带返回值的线程。
    • RUNNABLE

      运行中状态,其实这里应该是包含两种状态的,一种是就绪状态(即线程调用了start方法,但是不一定会立马运行,还需要等待系统OS的调度),另一种是运行状态(即正在执行中)。

    • BLOCKED

      阻塞状态,线程进入等待状态。而阻塞又分为多种情况。

      • 等待阻塞:线程执行wait方法,JVM将当前线程加入等待队列。
      • 同步阻塞:与其他线程竞争同步锁时,由于锁已被其他线程获取,进而被JVM加入同步队列。
      • 其他阻塞:Thread.sleep()joinIO等操作时,JVM会阻塞直至上述操作结束才会恢复线程。
    • WAITTING

      等待状态,线程进入等待,需要被唤醒。

    • TIME_WAITTING

      等待状态,超时以后自动返回。

    • TERMINATED

      终止状态,线程执行完毕退出。

    线程状态的转换

    线程的一生可能会经过以上六个阶段,那么它们之间又是怎么转换的呢,这里贴上流程转换的图:

    线程状态转换

    在图上可以看到一些操作,等到后面再慢慢介绍这些都是干嘛用的。

    我们也可以通过以下代码来演示一下线程的相关状态:

    public class ThreadStatus {
        public static void main(String[] args) {
            new Thread(() -> {
                while (true) {
                    try {
                        TimeUnit.SECONDS.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }, "time-waiting").start();
    
            new Thread(() -> {
                while (true) {
                    synchronized (ThreadStatus.class) {
                        try {
                            ThreadStatus.class.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }, "waiting").start();
    
            new Thread(new Block(),"Block-01").start();
            new Thread(new Block(),"Block-02").start();
        }
    
        static class Block extends Thread {
            @Override
            public void run() {
                synchronized (Block.class){
                    while(true){
                        try {
                            TimeUnit.SECONDS.sleep(100);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
            }
        }
    }
    

    这段代码运行起来之后,我们打开控制台,执行jps命令,这个命令可以获得相应Java进程的PID

    在执行jstack PID(PID是我们上一步拿到的)可以得到下面的dump信息。

    . . . . . .省略部分信息
    "Block-02" #16 prio=5 os_prio=31 tid=0x00007ffe1683e000 nid=0xa303 waiting for monitor entry [0x0000700006b83000]
       java.lang.Thread.State: BLOCKED (on object monitor)
            at top.felixu.chapter1.lifecycle.ThreadStatus$Block.run(ThreadStatus.java:44)
            - waiting to lock <0x000000076b0cdb00> (a java.lang.Class for top.felixu.chapter1.lifecycle.ThreadStatus$Block)
            at java.lang.Thread.run(Thread.java:748)
    
    "Block-01" #14 prio=5 os_prio=31 tid=0x00007ffe1683a000 nid=0xa503 waiting on condition [0x0000700006a80000]
       java.lang.Thread.State: TIMED_WAITING (sleeping)
            at java.lang.Thread.sleep(Native Method)
            at java.lang.Thread.sleep(Thread.java:340)
            at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
            at top.felixu.chapter1.lifecycle.ThreadStatus$Block.run(ThreadStatus.java:44)
            - locked <0x000000076b0cdb00> (a java.lang.Class for top.felixu.chapter1.lifecycle.ThreadStatus$Block)
            at java.lang.Thread.run(Thread.java:748)
    
    "waiting" #12 prio=5 os_prio=31 tid=0x00007ffe13089000 nid=0xa603 in Object.wait() [0x000070000697d000]
       java.lang.Thread.State: WAITING (on object monitor)
            at java.lang.Object.wait(Native Method)
            - waiting on <0x000000076aeed260> (a java.lang.Class for top.felixu.chapter1.lifecycle.ThreadStatus)
            at java.lang.Object.wait(Object.java:502)
            at top.felixu.chapter1.lifecycle.ThreadStatus.lambda$main$1(ThreadStatus.java:26)
            - locked <0x000000076aeed260> (a java.lang.Class for top.felixu.chapter1.lifecycle.ThreadStatus)
            at top.felixu.chapter1.lifecycle.ThreadStatus$$Lambda$2/668386784.run(Unknown Source)
            at java.lang.Thread.run(Thread.java:748)
    
    "time-waiting" #11 prio=5 os_prio=31 tid=0x00007ffe16839000 nid=0xa803 waiting on condition [0x000070000687a000]
       java.lang.Thread.State: TIMED_WAITING (sleeping)
            at java.lang.Thread.sleep(Native Method)
            at java.lang.Thread.sleep(Thread.java:340)
            at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
            at top.felixu.chapter1.lifecycle.ThreadStatus.lambda$main$0(ThreadStatus.java:15)
            at top.felixu.chapter1.lifecycle.ThreadStatus$$Lambda$1/764977973.run(Unknown Source)
            at java.lang.Thread.run(Thread.java:748)
    . . . . . .省略部分信息
    

    从上面的dump可以看到线程的大部分状态了,有些状态没法从dump的信息中看出来。

    结语

    不知道写点啥,拉倒吧,没有结语。

    参考自《Java并发编程的艺术》

    相关文章

      网友评论

          本文标题:线程的生命周期

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