线程的状态

张贤 2020年03月13日 95次浏览

Java 里的线程有 6 个状态,这 6 个状态与操作系统的里线程的状态有部分差异,原因是 Java 对操作系统的线程做了封装,下面来说说 Java 线程的状态和对应的操作系统的线程的状态。

  • 新建(New):创建后尚未启动的线程的状态,即使用 new 关键字创建了线程,但是还没有调用线程的 start() 方法。
  • 运行(Runnable):Java线程的 Runnable 状态包括操作系统里的 Ready 和 Running 状态。在 Java 中处于 Runnable 状态的线程有可能在执行状态,对应于操作系统层面的 Running;也有可能在等待 CPU 为这个线程分配时间片,对应于操作系统层面的 Ready。
  • 无限期等待(Waiting):处于这个状态的线程不会被分配 CPU 时间,需要显示唤醒。以下方法会让线程进入 Waiting 状态:
    • 没有设置 Timeout 参数的 Object.wait() 方法
    • 没有设置 Timeout 参数的 Thread.join() 方法
    • LockSupport.park() 方法
  • 限期等待(Timed Waiting):在一定时间后会由系统自动唤醒。以下方法会让线程进入 Timed Waiting 状态:
    • Thread.sleep() 方法
    • 设置了 Timeout 参数的 Object.wait() 方法
    • 设置了 Timeout 参数的 Thread.join() 方法
    • LockSupport.parkNanos() 方法
    • LockSupport.parkUntil() 方法
  • 阻塞(Blocked):等待获取排它锁
  • 结束状态(Terminated):已终止线程的状态,线程的 run() 方法已经运行完成。对一个已经终止的线程执行 start() 方法会抛出 IllegalThreadStateException 异常。下面的代码,在第二次执行 start() 方法时,线程已经处于终止状态,会抛出 IllegalThreadStateException 异常。
public class ThreadTest {
    private static void attack(){
        System.out.println("Fight");
        // 打印当前线程名字
        System.out.println("Current Thread is: "+ Thread.currentThread().getName());
    }

    public static void main(String[] args) throws InterruptedException {
        Thread t=new Thread(){
            @Override
            public void run() {
                //在子线程里面调用 attack 方法,打印线程名字
                attack();
            }
        };
        //打印主线程名字
        System.out.println("Current Thread is: "+ Thread.currentThread().getName());
        //打印线程名字
        t.start();
        //等待线程执行结束
        t.join();
        //这里会抛出 IllegalThreadStateException 异常
        t.start();
    }
}

在 Thread 类中定义了一个内部枚举类 State,其中就定义了上述 6 种状态:

    public enum State {
        NEW,

        RUNNABLE,

        BLOCKED,

        WAITING,

        TIMED_WAITING,

        TERMINATED;
    }

在类中也有详细的注释,需要的同学可以查看。