• Java 基础复习 Day 21


    Java 基础复习 Day 21

    多线程(3)

    1. 线程的状态描述

      线程一共有6种状态:在Thread的子类中Thread.State类中记载了线程的6种状态

      线程状态图描述:图片来自某网课,如侵权请联系删除
      在这里插入图片描述

    • 线程状态。线程可以处于以下状态之一:

      • NEW
        尚未启动的线程处于此状态。

      • RUNNABLE
        在Java虚拟机中执行的线程处于此状态。

      • BLOCKED
        被阻塞等待监视器锁定的线程处于此状态。

      • WAITING
        正在等待另一个线程执行特定动作的线程处于此状态。

      • TIMED_WAITING
        正在等待另一个线程执行动作达到指定等待时间的线程处于此状态。

      • TERMINATED
        已退出的线程处于此状态。

        在这里插入图片描述

    1. 线程状态通信案例(生产者-消费者问题)实现线程状态的互相转换: Waiting ⇒Runnable

      /*
      *
      * 等待唤醒案例分析:线程之间的通信
      *  step1:创建一个顾客线程(消费者):告知老板食物的数量和种类,然后调用wait方法时顾客线程进入waiting状态
      *  step2:创建一个老板线程(生产者):花了5秒钟做食物,并用notify来唤醒顾客让其食用
      *
      * 注意:生产者和消费者必须使用同步代码块,保证等待和唤醒在同一时刻只能有一个在执行
      *      同步使用的锁对象必须要唯一
      *       只有锁对象才能调用wait和notify方法
      * Object类中的wait和notify方法
      * void wait()
      导致当前线程等待,直到另一个线程调用该对象的 notify()方法或 notifyAll()方法。
      * void notify()
      唤醒正在等待对象监视器的单个线程。
      * 唤醒之后会执行wait之后的代码
      *
      * */
      public class DemoWaitandNortify {
          public static void main(String[] args) {
              //创建一个锁对象 并且唯一
              Object obj = new Object();
              //创建一个顾客线程(消费者)
              new Thread(new Runnable() {
                  @Override
                  public void run() {
                     while (true) {
                         synchronized (obj){
                             System.out.println("告知老板食物的数量和种类");
                             try {
                                 obj.wait();
                             } catch (InterruptedException e) {
                                 e.printStackTrace();
                             }
                             System.out.println("wait之后就开吃");
                         }
                     }
                  }
              }).start();
              new Thread(){
                  @Override
                  public void run() {
                     while (true){
                         try {
                             Thread.sleep(5000);
                         } catch (InterruptedException e) {
                             e.printStackTrace();
                         }
                         synchronized (obj){
                             System.out.println("花了5秒钟做食物后,唤醒顾客让其食用");
                             obj.notify();
                         }
                     }
                  }
              }.start();
      
          }
      }
      
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54
      • 55
      • 56
      • 57
      • 58
    2. Timed-Waiting状态

      /*
      *   进入到Timed-Waiting有两种方式,
      *   1.调用Thread中的方法sleep(long millis)
      使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行),具体取决于系统定时器和调度程序的精度和准确性。
      * 当sleep在参数的毫秒之后会进入到Running|Blocked状态
      *   2.调用Object带参数的wait(long timeout)
      导致当前线程等待,直到另一个线程调用 notify()方法或该对象的 notifyAll()方法,或者指定的时间已过。
      * 如果在指定的毫秒值之后还未被notify那么就会自动醒来
      * */
      public class DemoTimedWaiting {
          public static void main(String[] args) {
              //创建一个锁对象 并且唯一
              Object obj = new Object();
              //创建一个顾客线程(消费者)
              new Thread(new Runnable() {
                  @Override
                  public void run() {
                      while (true) {
                          synchronized (obj){
                              System.out.println("告知老板食物的数量和种类");
                              try {
                                  obj.wait(5000);
                              } catch (InterruptedException e) {
                                  e.printStackTrace();
                              }
                              System.out.println("wait之后就开吃");
                          }
                      }
                  }
              }).start();
          }
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
    3. notify vs notifyAll

      public static void main(String[] args) {
              //创建一个锁对象 并且唯一
              Object obj = new Object();
              //创建一个顾客1线程(消费者)
              new Thread(new Runnable() {
                  @Override
                  public void run() {
                      while (true) {
                          synchronized (obj){
                              System.out.println("顾客1告知老板食物的数量和种类");
                              try {
                                  obj.wait(5000);
                              } catch (InterruptedException e) {
                                  e.printStackTrace();
                              }
                              System.out.println("顾客1wait之后就开吃");
                          }
                      }
                  }
              }).start();
              //创建一个顾客2线程(消费者)
              new Thread(new Runnable() {
                  @Override
                  public void run() {
                      while (true) {
                          synchronized (obj){
                              System.out.println("顾客2告知老板食物的数量和种类");
                              try {
                                  obj.wait(5000);
                              } catch (InterruptedException e) {
                                  e.printStackTrace();
                              }
                              System.out.println("顾客2wait之后就开吃");
                          }
                      }
                  }
              }).start();
              //创建一个老板线程(生产者)
              new Thread(){
                  @Override
                  public void run() {
                      while (true){
                          try {
                              Thread.sleep(5000);
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          }
                          synchronized (obj){
                              System.out.println("花了5秒钟做食物后,唤醒顾客让其食用");
                              //obj.notify();//只能唤醒一个,当有两个以上的线程处于等待的状态就随机唤醒
                              obj.notifyAll();//把两个线程都唤醒,但由于1个生产者两消费者,会顾不过来,打印也会混乱
                          }
                      }
                  }
              }.start();
          }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53
      • 54
      • 55
      • 56
      顾客1告知老板食物的数量和种类
      顾客2告知老板食物的数量和种类
      顾客2wait之后就开吃
      顾客2告知老板食物的数量和种类
      花了5秒钟做食物后,唤醒顾客让其食用
      顾客1wait之后就开吃
      顾客1告知老板食物的数量和种类
      顾客2wait之后就开吃
      顾客2告知老板食物的数量和种类
      顾客1wait之后就开吃
      顾客1告知老板食物的数量和种类
      顾客2wait之后就开吃
      顾客2告知老板食物的数量和种类
      花了5秒钟做食物后,唤醒顾客让其食用
      顾客2wait之后就开吃
      顾客2告知老板食物的数量和种类
      顾客1wait之后就开吃
      顾客1告知老板食物的数量和种类
      顾客1wait之后就开吃
      顾客1告知老板食物的数量和种类
      花了5秒钟做食物后,唤醒顾客让其食用
      顾客2wait之后就开吃
      顾客2告知老板食物的数量和种类
      顾客1wait之后就开吃
      顾客1告知老板食物的数量和种类
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
  • 相关阅读:
    深夜小酌,50道经典SQL题,真香~
    第一章:最新版零基础学习 PYTHON 教程(第七节 - Python 中的语句、缩进和注释)
    html+css实现全局固定位置悬浮的菜单
    Move 合约漏洞,Move 合约中最常见的 10 种 Bug
    5G-Advanced核心网技术综述
    【VUE复习·6】监视属性watch:用途、两种写法、简写、应用时注意事项(重点)、深度监视(重点)
    3、传统的Synchronized锁
    HXAPIGate系列——HXAPIGate快速入门
    C++初阶 入门(2)
    中国凸轮滑块单元行业发展态势与投资趋势预测报告2022-2028年
  • 原文地址:https://blog.csdn.net/karenkou/article/details/126164199