用java实现线程的各种状态

116 阅读3分钟

1、java里线程状态概述

在java中,使用Thread.currentThread().getState()可以查看当前线程的状态。 而java中的线程状态可以概括为以下六种

1. NEW :

当线程对象被创建时,它处于新建状态。此时,线程还没有开始执行。

2. RUNNABLE :

在调用线程的 start() 方法后,线程进入可运行状态。表示线程已经准备好执行,但可能还未获得 CPU 时间片来执行。

  • 包括READY和RUNNING两种细分状态
3. WAITING:

线程在等待其他线程发出特定信号或条件时进入等待状态。线程可以通过 wait() 方法或其他类似的方法使自己进入等待状态。

4. TIMED WAITING:

类似于等待状态,但在等待一段特定的时间后会自动返回可运行状态。线程可以通过 sleep() 方法、join() 方法或其他类似的方法进入计时等待状态。

5. BLOCKED:

线程在某些情况下无法继续执行时,进入阻塞状态。这可能是由于等待某个资源、等待锁的释放、等待输入/输出操作完成等原因。

6. TERMINATED:

线程结束

2、编程实现线程各种状态

1)、工具类准备

主要是控制线程的睡眠时间,可以控制线程的唤醒顺序,自主控制线程对资源的利用顺序。 定义一个静态辅助类 SleepHelper, 其中包含了两个静态方法 sleepSecondssleepMilli,用于实现线程的睡眠功能。

  1. sleepSeconds 方法接受一个整数参数 seconds,表示需要睡眠的秒数。通过调用 TimeUnit.SECONDS.sleep(seconds) 方法,让当前线程睡眠指定的秒数。
  2. sleepMilli 方法接受一个整数参数 i,表示需要睡眠的毫秒数。通过调用 TimeUnit.MILLISECONDS.sleep(i) 方法,让当前线程睡眠指定的毫秒数。

这些方法提供了一种方便的方式来使当前线程睡眠一段时间,以控制线程的执行速度、时间间隔或延迟等操作。

public static class SleepHelper {
    public static void sleepSeconds(int seconds) {
        try {
            TimeUnit.SECONDS.sleep(seconds);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void sleepMilli(int i) {
        try {
            TimeUnit.MILLISECONDS.sleep(i);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

2)、线程状态代码实现

(1)、线程创建和线程运行

// 创建一个线程并在内部输出当前状态,只有线程运行时才会进入到内部执行代码,所以输出结果为 RUNNABLE
Thread t1 = new Thread(() -> {
    System.out.println("2:" + Thread.currentThread().getState());
    for (int i = 0; i < 3; i++) {
        SleepHelper.sleepSeconds(1);
        System.out.print(i + "  ");
    }
    System.out.println();
});
// 此时创建线程输出结果为NEW
System.out.println("1:" + t1.getState());
// 线程唤醒此时进入到上面的lambda语句块中
t1.start();
// 线程结束
t1.join();
// 线程结束输出TERMINATED
System.out.println("3:" + t1.getState());

2)、线程的WAITING和TIMED WAITING

// 在创建时给线程加上锁,控制线程为WAITING
Thread t2 = new Thread(() -> {
    try {
        LockSupport.park();
        System.out.println("t2 go on!");
        TimeUnit.SECONDS.sleep(5);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
});
// 此时启动线程
t2.start();
// 使用工具使线程等待一秒,确保线程已经完全启动
TimeUnit.SECONDS.sleep(1);
// 此时输出线程状态,结果为WAITING
System.out.println("4:" + t2.getState());
// 在此时给线程释放锁
LockSupport.unpark(t2);
// 等待一秒,确保线程的Lock被完全释放
TimeUnit.SECONDS.sleep(1);
// 由于线程内部也在睡眠并且时间为5秒,但是线程已经获得资源,所以线程此时的状态为TIMED WAITING
System.out.println("5:" + t2.getState());

3)、线程的BLOCKED

final Object o = new Object();
// 创建线程时请求获取资源o
Thread t3 = new Thread(() -> {
    synchronized (o) {
        System.out.println("t3 得到了锁 o");
    }
});
// 创建另一个线程,直接启动,占用资源o五秒,
new Thread(() -> {
    synchronized (o) {
        SleepHelper.sleepSeconds(5);
    }
}).start();
// 主程序睡眠1秒,确保上面占用资源的线程启动
SleepHelper.sleepSeconds(1);
// 启动t3线程
t3.start();
// 睡眠一秒确保线程完全启动
SleepHelper.sleepSeconds(1);
// 此时t3请求o资源被占用,线程是BLOCKED状态
System.out.println("6:" + t3.getState());

3、整体代码

public static void main(String[] args) throws Exception {
        //===================================================

        // 创建一个线程并在内部输出当前状态,只有线程运行时才会进入到内部执行代码,所以输出结果为 RUNNABLE
        Thread t1 = new Thread(() -> {
            System.out.println("2:" + Thread.currentThread().getState());
            for (int i = 0; i < 3; i++) {
                SleepHelper.sleepSeconds(1);
                System.out.print(i + "  ");
            }
            System.out.println();
        });
        // 此时创建线程输出结果为NEW
        System.out.println("1:" + t1.getState());
        // 线程唤醒此时进入到上面的lambda语句块中
        t1.start();
        // 线程结束
        t1.join();
        // 线程结束输出TERMINATED
        System.out.println("3:" + t1.getState());
        //===================================================
        Thread t2 = new Thread(() -> {
            try {
                LockSupport.park();
                System.out.println("t2 go on!");
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        t2.start();
        TimeUnit.SECONDS.sleep(1);
        System.out.println("4:" + t2.getState());
        LockSupport.unpark(t2);
        TimeUnit.SECONDS.sleep(1);
        System.out.println("5:" + t2.getState());
        //===================================================
        final Object o = new Object();
        Thread t3 = new Thread(() -> {
            synchronized (o) {
                System.out.println("t3 得到了锁 o");
            }
        });

        new Thread(() -> {
            synchronized (o) {
                SleepHelper.sleepSeconds(5);
            }
        }).start();

        SleepHelper.sleepSeconds(1);
        t3.start();
        SleepHelper.sleepSeconds(1);
        System.out.println("6:" + t3.getState());

        //===================================================

        final Lock lock = new ReentrantLock();
        Thread t4 = new Thread(() -> {
            lock.lock(); //省略try finally
            System.out.println("t4 得到了锁 o");
            lock.unlock();
        });

        new Thread(() -> {
            lock.lock();
            SleepHelper.sleepSeconds(5);
            lock.unlock();
        }).start();

        SleepHelper.sleepSeconds(1);

        t4.start();
        SleepHelper.sleepSeconds(1);
        System.out.println("7: " + t4.getState());

        //===================================================

        //===================================================
        Thread t5 = new Thread(() -> {
            LockSupport.park();
        });

        t5.start();

        SleepHelper.sleepSeconds(1);

        System.out.println("8: " + t5.getState());
        LockSupport.unpark(t5);
    }