Java中多线程中的线程状态概述: Timed Waiting(计时等待); BLOCKED(阻塞锁); Waiting(无限等待)

JVM虚拟机中线程的状态转换图

Java中多线程中的线程状态概述: Timed Waiting(计时等待); BLOCKED(阻塞锁); Waiting(无限等待)_第1张图片

  • new完线程后,各个线程开始抢cpu,抢到的进入运行状态,没有抢到的进入阻塞状态,阻塞状态和运行状态可以相互转换(多个线程一起抢夺cpu的使用权)。
  • run出现异常或者结束的话会进入死亡状态。
  • 运行状态可以进入睡眠状态,睡眠结束若cpu空闲,进入运行状态,若不空闲,进入阻塞状态。
  • 休眠是可以自己醒的,无限等待状态是不能自己醒的,需要借助Object类中的方法

Timed Waiting(计时等待)

Java中多线程中的线程状态概述: Timed Waiting(计时等待); BLOCKED(阻塞锁); Waiting(无限等待)_第2张图片

锁阻塞状态

Java中多线程中的线程状态概述: Timed Waiting(计时等待); BLOCKED(阻塞锁); Waiting(无限等待)_第3张图片

等待与唤醒

Java中多线程中的线程状态概述: Timed Waiting(计时等待); BLOCKED(阻塞锁); Waiting(无限等待)_第4张图片

等待唤醒案例:线程之间的通信

  1. 创建一个顾客线程(消费者):告知老板要的包子的种类和数量,调用wait方法,放弃cpu的执行,进入到WAITING状态(无限等待)
  2. 创建一个老板线程(生产者):花了5秒做包子,做好包子之后,调用notify方法,唤醒顾客吃包子

注意:

  • 顾客和老板线程必须使用同步代码块包裹起来,保证等待和唤醒只能有一个在执行
  • 同步使用的锁对象必须保证唯一
  • 只有锁对象才能调用wait和notify方法

Obejct类中的方法

void wait()
      在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待。
void notify()
      唤醒在此对象监视器上等待的单个线程。
      会继续执行wait方法之后的代码

代码实现

public class DemoWaitAndNotify {
    public static void main(String[] args) {
        //创建一个唯一的锁对象
        Object objLock = new Object();

        //创建一个顾客:消费者
        new Thread() {
            @Override
            public void run() {
                //保证要么是消费者在告诉老板,要么是老板在做,所以需要同步代码块
                System.out.println("告诉老板有消费者要吃包子的种类和数量,然后等待....");
                synchronized (objLock) {
                    //消费者等待老板做完
                    try {
                        //调用wait方法,放弃cpu的执行,进入到WAITING状态(无限等待)并释放锁
                        //被醒来之后会继续朝着wait()之后的语句执行
                        objLock.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                System.out.println("消费者吃包子....");
            }
        }.start();

        //创建一个老板,生产者
        new Thread() {
            @Override
            public void run() {
                try {
                    sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                //老板在做某一个包子的过程中,不允许顾客再提要求,也不可能让顾客吃,所以也要同步代码块
                synchronized (objLock) {
                    System.out.println("老板5s之后做好了包子,通知顾客");
                    objLock.notify();
                }
            }
        }.start();
    }
}

运行结果

告诉老板有消费者要吃包子的种类和数量,然后等待....
老板5s之后做好了包子,通知顾客
消费者吃包子....

这段代码的执行逻辑是:一开始两个线程共同争夺cpu资源,而生产者线程上来就sleep()。所以一开始一定是消费者执行,执行到wait()时主动释放cpu资源,在接下来的过程中,没有收到notify()的话就不会继续往下执行。所以等到生产者完成包子的生产之后,通知消费者可以恢复了(消费者才能吃)----->线程间的通讯

你可能感兴趣的:(Java多线程基础)