Java 线程状态有哪些?

文章目录

  • Java 线程状态有哪些?
    • 初始状态(NEW)
    • 可运行状态(RUNNABLE)
      • 就绪状态
      • 运行状态
    • 阻塞状态(BLOCKED)
    • 等待状态(WAITING)
    • 超时等待(TIMED_WAITING)
    • 终止状态(TERMINATED)

Java 线程状态有哪些?

在线程的生命周期中,它需要经历初始状态、可运行状态、阻塞状态、等待状态、超时等待状态和终止状态。线程的状态流转如下图所示。

Java 线程状态有哪些?_第1张图片

下面的示例代码都继承自类,用来按步骤(模拟时间序列)输出线程的状态。

package org.gettingreal.juc.learning.thread;

/**
 * 线程状态打印类
 */
public class ThreadStatePrinter {

    // 记录步骤
    private static volatile int STEP = 0;

    // 打印状态
    public static void printState(Thread thread) {
        System.out.println("STEP: " + (++STEP) + ", " + thread.getName() + "'s state: " + thread.getState());
    }

}

初始状态(NEW)

继承 Thread 类,或者类实现 Runnable 接口并将其传递给 Thread 类,使用 new 操作符来创建一个线程,线程此时的状态是初始状态。

package org.gettingreal.juc.learning.thread;

/**
 * 线程初始化状态测试
 */
public class ThreadNewStateTest extends ThreadStatePrinter {

    public static void main(String[] args) {
        Thread t = new Thread();
        printState(t);

        // 输出
        // STEP: 1, Thread-0's state: NEW
    }

}

可运行状态(RUNNABLE)

线程的可运行状态较为复杂,因为隐喻了就绪状态和运行状态。

就绪状态

就绪状态,是指线程有被运行的可能,CPU 分配给该线程时间片,该线程就会进入运行状态。

下面是线程进入就绪状态的场景:

  • 调用线程的 start() 方法
  • 线程 sleep() 方法结束
  • 其他线程 join() 结束
  • 时间片用完或调用线程的 yield() 方法
  • 锁池里面的线程拿到锁后

通过 start() 方法使得线程进入 RUNNABLE 状态。

package org.gettingreal.juc.learning.thread;

/**
 * 线程 RUNNABLE 状态测试
 */
public class ThreadRunnableStateWithStartTest extends ThreadStatePrinter {

    public static void main(String[] args) {
        Thread t = new Thread();
        printState(t);

        t.start();
        printState(t);

        // 输出
        // STEP: 1, Thread-0's state: NEW
        // STEP: 2, Thread-0's state: RUNNABLE
    }

}

线程 sleep() 方法结束,进入 RUNNABLE 状态。

package org.gettingreal.juc.learning.thread;

/**
 * 线程 RUNNABLE 状态测试
 */
public class ThreadRunnableStateWithSleepTest extends ThreadStatePrinter {


    public static void main(String[] args) throws Exception {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    // 触发睡眠
                    Thread.sleep(3000);

                    // 睡眠之后打印该线程的状态
                    printState(Thread.currentThread());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        printState(t);

        t.start();
        printState(t);

        // 主线程睡眠 1 秒中,为了输出睡眠中线程的状态
        Thread.sleep(1000);
        printState(t);

        // 输出
        // STEP: 1, Thread-0's state: NEW
        // STEP: 2, Thread-0's state: RUNNABLE
        // STEP: 3, Thread-0's state: TIMED_WAITING
        // STEP: 4, Thread-0's state: RUNNABLE
    }

}

可以看出,当线程调用 sleep() 方法后,线程进入 TIMED_WAITING 状态,等到 sleep 结束,线程又进入到 RUNNABLE 状态。

其他线程 join 结束,线程进入 RUNNABLE 状态。

package org.gettingreal.juc.learning.thread;

/**
 * 线程 RUNNABLE 状态测试
 */
public class ThreadRunnableStateWithSleepTest extends ThreadStatePrinter {

    private static Thread parentThread;
    private static Thread childThread;

    public static void main(String[] args) throws Exception {
        childThread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    // 触发睡眠
                    Thread.sleep(3000);

                    // 睡眠之后打印父线程的状态
                    printState(parentThread);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        childThread.setName("childThread");

        parentThread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {

                    childThread.start();
                    childThread.join();

                    // join 结束后打印父线程状态
                    printState(parentThread);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        parentThread.setName("parentThread");

        printState(parentThread);

        parentThread.start();
        printState(parentThread);


        // 输出
        // STEP: 1, parentThread's state: NEW
        // STEP: 2, parentThread's state: RUNNABLE
        // STEP: 3, parentThread's state: WAITING
        // STEP: 4, parentThread's state: RUNNABLE
    }

}

可以看出,parentThread 线程在 WAITING 状态之后又恢复到 RUNNABLE 状态。

时间片用完或者调用 yield() 方法。

package org.gettingreal.juc.learning.thread;

/**
 * 线程 RUNNABLE 状态测试
 */
public class ThreadRunnableStateWithYieldTest extends ThreadStatePrinter {

    public static void main(String[] args) {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                printState(Thread.currentThread());

                // 正在运行中的线程,时间片用完或者调用 yield 方法,都会让线程进入 RUNNABLE 抓给你台
                Thread.yield();

                printState(Thread.currentThread());
            }
        });
        printState(t);

        t.start();
        printState(t);

        // 输出
        // STEP: 1, Thread-0's state: NEW
        // STEP: 2, Thread-0's state: RUNNABLE
        // STEP: 3, Thread-0's state: RUNNABLE
        // STEP: 4, Thread-0's state: RUNNABLE
    }

}

运行状态

从就绪状态的线程中选择一个线程,分配给其 CPU 时间片来运行,该线程就进入运行状态。

阻塞状态(BLOCKED)

当线程无法获取锁时,就会进入到阻塞状态。

package org.gettingreal.juc.learning.thread;

/**
 * 线程阻塞状态测试
 */
public class ThreadBlockedStateTest extends ThreadStatePrinter {

    // 使用对象来模拟一把锁
    private static Object lock = new Object();
    private static Thread oneThread;
    private static Thread anotherThread;

    public static void main(String[] args) throws Exception {
        oneThread = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lock) {
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        oneThread.setName("oneThread");

        anotherThread = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lock) {
                    try {
                        Thread.sleep(3000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
        anotherThread.setName("anotherThread");
        printState(oneThread);
        printState(anotherThread);

        oneThread.start();
        anotherThread.start();

        printState(oneThread);
        printState(anotherThread);

        Thread.sleep(1500);

        printState(oneThread);
        printState(anotherThread);

        Thread.sleep(1500);
        printState(oneThread);
        printState(anotherThread);

        // 输出
        // STEP: 1, oneThread's state: NEW
        // STEP: 2, anotherThread's state: NEW
        // STEP: 3, oneThread's state: TIMED_WAITING
        // STEP: 4, anotherThread's state: RUNNABLE
        // STEP: 5, oneThread's state: TIMED_WAITING
        // STEP: 6, anotherThread's state: BLOCKED
        // STEP: 7, oneThread's state: TERMINATED
        // STEP: 8, anotherThread's state: TIMED_WAITING
    }

}

可以看到在第六步时,anotherThread 的状态是 BLOCKED,因为该线程也需要获得 lock 锁才能执行 synchronized 块里面的逻辑。

等待状态(WAITING)

处于等待状态的线程不会被分配 CPU 执行时间,要被显式地唤醒(调用 notify() 方法),否则会处于一直等待的状态。调用 wait() 方法会释放锁,线程会进入等待锁池中。

package org.gettingreal.juc.learning.thread;

/**
 * 线程等待状态测试
 */
public class ThreadWaitingStateTest extends ThreadStatePrinter {

    private static final Object lock = new Object();

    public static void main(String[] args) throws Exception {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (lock) {
                    try {
                        // 调用 wait 方法进入等待状态
                        lock.wait();

                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        });

        printState(t);

        t.start();
        printState(t);

        // 睡眠 1 秒钟,让 t 线程的 wait() 方法得到执行
        Thread.sleep(1000);
        printState(t);

        // 通知线程 t
        synchronized (lock) {
            lock.notify();
            printState(t);
        }

        // 输出
        // STEP: 1, Thread-0's state: NEW
        // STEP: 2, Thread-0's state: RUNNABLE
        // STEP: 3, Thread-0's state: WAITING
        // STEP: 4, Thread-0's state: BLOCKED
    }

}

在线程上调用 wait() 方法,该线程会进入 WAITING 状态,释放 lock 锁。后面的 BLOCKED 状态是因为执行完 notify() 方法之后,线程需要再次获取 lock 锁。

超时等待(TIMED_WAITING)

线程处于超时等待状态的不会被分配 CPU 执行时间,也无需被唤醒,当然也不会释放对应的锁。

package org.gettingreal.juc.learning.thread;

/**
 * 线程超时等待状态测试
 */
public class ThreadTimedWaitingStateTest extends ThreadStatePrinter {

    private static final Object lock = new Object();

    public static void main(String[] args) throws Exception {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(3000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        printState(t);

        t.start();
        printState(t);

        // 睡眠 1 秒钟,让 t 线程的 wait() 方法得到执行
        Thread.sleep(1000);
        printState(t);

        // 输出
        // STEP: 1, Thread-0's state: NEW
        // STEP: 2, Thread-0's state: RUNNABLE
        // STEP: 3, Thread-0's state: TIMED_WAITING
    }

}

终止状态(TERMINATED)

线程的 run() 方法执行完成后,该线程的状态就是终止状态了。

package org.gettingreal.juc.learning.thread;

/**
 * 线程终止状态测试
 */
public class ThreadTerminatedStateTest extends ThreadStatePrinter {

    private static final Object lock = new Object();

    public static void main(String[] args) throws Exception {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {

            }
        });

        printState(t);

        t.start();
        printState(t);

        // 睡眠 1 秒钟,让 t 线程的 wait() 方法得到执行
        Thread.sleep(1000);
        printState(t);

        // 输出
        // STEP: 1, Thread-0's state: NEW
        // STEP: 2, Thread-0's state: RUNNABLE
        // STEP: 3, Thread-0's state: TERMINATED
    }

}

你可能感兴趣的:(Java,java,线程,状态,生命周期)