3.3 JAVA线程状态

109 阅读3分钟

一、五大状态

image.png

  • 创建状态:new的时候,一旦创建就进入到该状态
  • 就绪状态:调用start()时,等待CPU调度,进入该状态
  • 运行状态:CPU真正调用该线程的时候
  • 阻塞状态:等待用户输入或者sleep()
  • 死亡状态:线程中断或者结束,一旦进入死亡就不能再次启动

二、线程方法

image.png

2.1 线程停止

  • 不推荐JDK提供的stop()destroy()方法(已废弃)
  • 推荐线程自己停止下来
  • 建议使用一个标志位进行终止变量
 /**
  * @ClassName ThreadStop
  * @Description
  * 停止线程,建议线程自己停止,使用标志位
  * 不要使用JDK中stop和destroy
  * @Author wangwk-a
  * @Date 2022/1/1 19:47
  * @Version 1.0
  */
 public class ThreadStop implements Runnable{
     public static final int THREAD_LOOP = 50;
     public static final int STOP_THREAD_TIMES = 30;
 ​
     /**
      * TODO: 1. 设置一个标志位
      */
     private Boolean flag = true;
 ​
     @Override
     public void run() {
         int i = 0;
         while (flag) {
             System.out.println(Thread.currentThread().getName() + "线程正在执行" + i++);
         }
     }
 ​
     /**
      * TODO: 2. 设置一个公开的方法停止线程
      */
     public void stopThread() {
         this.flag = false;
     }
 ​
     public static void main(String[] args) {
 ​
         ThreadStop threadStop = new ThreadStop();
         new Thread(threadStop).start();
         for (int i = 0; i < THREAD_LOOP; i++) {
             System.out.println(Thread.currentThread().getName() + "线程正在执行" + i);
             if (i == STOP_THREAD_TIMES) {
                 threadStop.stopThread();
                 System.out.println("线程该停止了");
             }
         }
     }
 }
 main线程正在执行0
 main线程正在执行1
 Thread-0线程正在执行0
 Thread-0线程正在执行1
 main线程正在执行2
 Thread-0线程正在执行2
 main线程正在执行3
 main线程正在执行4
 main线程正在执行5
 Thread-0线程正在执行3
 Thread-0线程正在执行4
 Thread-0线程正在执行5
 Thread-0线程正在执行6
 Thread-0线程正在执行7
 Thread-0线程正在执行8
 Thread-0线程正在执行9
 main线程正在执行6
 main线程正在执行7
 main线程正在执行8
 main线程正在执行9
 main线程正在执行10
 main线程正在执行11
 main线程正在执行12
 main线程正在执行13
 Thread-0线程正在执行10
 main线程正在执行14
 main线程正在执行15
 main线程正在执行16
 main线程正在执行17
 Thread-0线程正在执行11
 main线程正在执行18
 Thread-0线程正在执行12
 main线程正在执行19
 main线程正在执行20
 main线程正在执行21
 main线程正在执行22
 Thread-0线程正在执行13
 Thread-0线程正在执行14
 Thread-0线程正在执行15
 Thread-0线程正在执行16
 Thread-0线程正在执行17
 Thread-0线程正在执行18
 Thread-0线程正在执行19
 Thread-0线程正在执行20
 Thread-0线程正在执行21
 Thread-0线程正在执行22
 Thread-0线程正在执行23
 Thread-0线程正在执行24
 Thread-0线程正在执行25
 Thread-0线程正在执行26
 Thread-0线程正在执行27
 Thread-0线程正在执行28
 Thread-0线程正在执行29
 main线程正在执行23
 main线程正在执行24
 main线程正在执行25
 Thread-0线程正在执行30
 Thread-0线程正在执行31
 Thread-0线程正在执行32
 main线程正在执行26
 main线程正在执行27
 main线程正在执行28
 main线程正在执行29
 main线程正在执行30
 Thread-0线程正在执行33
 线程该停止了
 main线程正在执行31
 main线程正在执行32
 main线程正在执行33
 main线程正在执行34
 main线程正在执行35
 main线程正在执行36
 main线程正在执行37
 main线程正在执行38
 main线程正在执行39
 main线程正在执行40
 main线程正在执行41
 main线程正在执行42
 main线程正在执行43
 main线程正在执行44
 main线程正在执行45
 main线程正在执行46
 main线程正在执行47
 main线程正在执行48
 main线程正在执行49
 ​
 Process finished with exit code 0

2.2 线程休眠Sleep

  • sleep(时间)指定当前线程阻塞的毫秒数
  • sleep存在InterruptedException
  • sleep时间打倒后线程进入就绪状态
  • sleep可以模拟网络延时,倒计时等
  • 每一个对象都有一个锁,sleep不会释放锁
 /**
  * @ClassName ThreadSleep
  * @Description 模拟倒计时
  * @Author wangwk-a
  * @Date 2022/1/1 20:05
  * @Version 1.0
  */
 public class ThreadSleep {
     public void tenDown() throws InterruptedException {
         int num = 10;
 ​
         while (true) {
             Thread.sleep(1000);
             System.out.println(num--);
             if (num <= 0) {
                 break;
             }
         }
     }
 ​
     public static void main(String[] args) {
         ThreadSleep threadSleep = new ThreadSleep();
         try {
             threadSleep.tenDown();
         } catch (InterruptedException e) {
             e.printStackTrace();
         }
     }
 }
 10
 9
 8
 7
 6
 5
 4
 3
 2
 1
 ​
 Process finished with exit code 0

2.3 线程礼让Yield

  • 礼让线程,让当前正在执行的线程暂停,但不阻塞
  • 将线程从运行状态转为就绪状态
  • 让CPU重新调度,礼让不一定成功,看CPU状态
/**
 * @ClassName ThreadYield
 * @Description 测试礼让线程,礼让不一定成功
 * @Author wangwk-a
 * @Date 2022/1/1 20:14
 * @Version 1.0
 */
public class ThreadYield {
    public static void main(String[] args) {
        MyYield myYield = new MyYield();
        /**
         * 如果礼让成功:
         * a线程开始执行
         * b线程开始执行
         * b线程结束执行
         */
        new Thread(myYield, "a").start();
        new Thread(myYield, "b").start();
    }
}

class MyYield implements Runnable {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "线程开始执行");
        // 线程礼让
        Thread.yield();
        System.out.println(Thread.currentThread().getName() + "线程结束执行");
    }
}
// 礼让成功
a线程开始执行
b线程开始执行
a线程结束执行
b线程结束执行

// 礼让不成功
a线程开始执行
a线程结束执行
b线程开始执行
b线程结束执行

2.4 线程合并Join

  • Join合并线程,待此线程执行完成后,再执行其他线程,其他线程阻塞
  • 可以想想成插队
/**
 * @ClassName threadJoin
 * @Description 测试线程合并,想想为插队
 * @Author wangwk-a
 * @Date 2022/1/1 20:21
 * @Version 1.0
 */
public class ThreadJoin implements Runnable{

    public static final int THREAD_LOOP = 10;
    public static final int MAIN_THREAD_LOOP = 30;
    public static final int JOIN_TIMES = 5;

    @Override
    public void run() {
        for (int i = 0; i < THREAD_LOOP; i++) {
            System.out.println("线程VIP来了--" + i);
        }
    }

    public static void main(String[] args) throws InterruptedException {
        ThreadJoin threadJoin = new ThreadJoin();
        Thread thread = new Thread(threadJoin);

        for (int i = 0; i < MAIN_THREAD_LOOP; i++) {
            if (i == JOIN_TIMES) {
                // 插队
                thread.start();
                thread.join();
            }
            System.out.println("Main--" + i);
        }
    }
}
Main--0
Main--1
Main--2
Main--3
Main--4
线程VIP来了--0
线程VIP来了--1
线程VIP来了--2
线程VIP来了--3
线程VIP来了--4
线程VIP来了--5
线程VIP来了--6
线程VIP来了--7
线程VIP来了--8
线程VIP来了--9
Main--5
Main--6
Main--7
Main--8
Main--9
Main--10
Main--11
Main--12
Main--13
Main--14
Main--15
Main--16
Main--17
Main--18
Main--19
Main--20
Main--21
Main--22
Main--23
Main--24
Main--25
Main--26
Main--27
Main--28
Main--29

Process finished with exit code 0

三、线程状态观测

**Thread.State**可以处于一下状态之一:

  • NEW:尚未启动的线程处于此状态
  • RUNNABLE:在Java虚拟机中执行的线程处于此状态
  • BLOCKED:被阻塞等待监视器锁定的线程处于此状态
  • WAITTING:正在等待另一个线程执行特定动作的线程处于此状态
  • TIMED WAITTING:正在等待另一个线程执行动作达到指定等待时间的线程处于此状态
  • TERMINATED:已退出的线程处于此状态

一个线程可以在给定时间点处于一个状态,这些状态时不反应任何操作系统线程状态的虚拟机状态。

/**
 * @ClassName ThreadStatus
 * @Description 观测线程状态
 * @Author wangwk-a
 * @Date 2022/1/1 20:36
 * @Version 1.0
 */
public class ThreadStatus {

    public static final int THREAD_LOOP = 1;

    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(()->{
            for (int i = 0; i < THREAD_LOOP; i++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("//////");
        });

        // NEW
        Thread.State stateNew = thread.getState();
        System.out.println(stateNew);

        // RUNNABLE
        thread.start();
        Thread.State stateRunnable = thread.getState();
        System.out.println(stateRunnable);

        // 只要线程不终止,就一直输出状态
        while (stateRunnable != Thread.State.TERMINATED) {
            Thread.sleep(100);
            // 更新线程状态
            stateRunnable = thread.getState();
            System.out.println(stateRunnable);
        }
    }
}
NEW
RUNNABLE
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
TIMED_WAITING
//////
TERMINATED

四、线程优先级

  • Java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照优先级决定应该调度哪个线程来执行
  • 线程优先级用数字表示,范围从1~10
    • Thread.MIN_PRIORITY = 1;
    • Thread.MAX_PRIORITY = 10;
    • Thread.MORM_PRIORITY = 5;
  • 使用以下方式改变或获取线程优先级
    • getPriority()
    • setPriority(int xxx)

/**
 * @ClassName ThreadPriorityTest
 * @Description 测试线程优先级
 * @Author wangwk-a
 * @Date 2022/1/1 20:49
 * @Version 1.0
 */
public class ThreadPriorityTest {
    public static void main(String[] args) {
        System.out.println("Main -->" + Thread.currentThread().getPriority());

        MyPriority myPriority = new MyPriority();
        Thread thread1 = new Thread(myPriority);
        Thread thread2 = new Thread(myPriority);
        Thread thread3 = new Thread(myPriority);
        Thread thread4 = new Thread(myPriority);

        // 先设置优先级
        thread1.start();

        thread2.setPriority(1);
        thread2.start();

        thread3.setPriority(4);
        thread3.start();

        thread4.setPriority(Thread.MAX_PRIORITY);
        thread4.start();
    }
}

class MyPriority implements Runnable {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + "-->" + Thread.currentThread().getPriority());
    }
}
Main -->5
Thread-0-->5
Thread-1-->1
Thread-3-->10
Thread-2-->4

Process finished with exit code 0

优先级低只是意味着获得调度的概率低,并不是优先级低就不会被调用,这都看CPU的调度

五、守护线程Daemon

  • 线程分为用户线程守护线程
  • JVM必须确保用户线程执行完毕
  • JVM不必等待守护线程执行完毕
  • 守护线程一般后台记录操作日志监控内存垃圾回收
/**
 * @ClassName DaemonTEst
 * @Description 测试守护线程
 * @Author wangwk-a
 * @Date 2022/1/1 21:13
 * @Version 1.0
 */
public class DaemonTest {
    public static void main(String[] args) {
        God god = new God();
        You you = new You();

        Thread daemonThread = new Thread(god);
        // 设置为守护线程
        daemonThread.setDaemon(true);
        daemonThread.start();

        new Thread(you).start();
    }
}

class God implements Runnable {
    @Override
    public void run() {
        while (true) {
            System.out.println("上帝保佑你");
        }
    }
}

class You implements Runnable {
    public static final int THREAD_LOOP = 30;
    @Override
    public void run() {
        for (int i = 0; i < THREAD_LOOP; i++) {
            System.out.println("你开心的活着");
        }
        System.out.println("=======GoodBye World=======");
    }
}
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
你开心的活着
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
=======GoodBye World=======
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
上帝保佑你
Process finished with exit code 0