双线程利用wait、notifyAll实现交替打印输出

  • wait与notify
  1. wait与notify以及notifyAll都是Object类中的方法,不是Thread类中的方法。
  2. 三个方法都必须写在同步代码块中。
  3. 方法的调用者必须是 synchronized 用的锁对象。
  4. wait方法调用 表示让当前线程进入一个等待状态,同时释放synchronized 的锁,当前线程则一直停留在wait方法。由于synchronized 释放了锁,则其他线程可以获取到锁。

通过阅读JDK源码,调用了wait方法的线程状态时WAITING。
在这里插入图片描述

  1. notify 方法,唤醒同一个synchronized 锁对象调用wait方法进入等待状态的线程,notify方法不会释放锁,会正常执行业务逻辑,唤醒了wait线程以后,被唤醒的哪些wait线程可以执行代码了,但是必须要等到notify的线程执行到wait时才可以,因为synchronized 代码块保证了同一时刻最多只能有一个线程去执行。一旦进入到wait,就是释放锁,线程进入WAITING状态,其他线程会继续竞争锁,继续执行。

  2. wait和notify是线程之间通信的重要方法,明确这两个方法的执行时机,会不会释放锁,释放锁之后的操作等等。

  • 双线程交替打印0-100
public class PrintThread {

    public static void main(String[] args) throws InterruptedException {

        Counter counter = new Counter();

        Thread t1 = new Thread(() -> {
            try {
                for (int i = 0; i < 100; i+=2) {
                    counter.print(i);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        t1.setName("t1");

        Thread t2 = new Thread(() -> {
            try {
                for (int i = 1; i < 100; i+=2) {
                    counter.print(i);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        t2.setName("t2");

        t1.start();
        t2.start();




    }


}

class Counter {

    public synchronized void print(int i) throws InterruptedException {
        notifyAll();
        System.out.println(Thread.currentThread().getName() + " ====> " + i);
        Thread.sleep(10);
        wait();
    }

}

分析此代码逻辑:

  1. main线程创建了2个线程,这两个线程分别调用同一个对象的print方法。
  2. 假设t1线程先进入print方法,传入0,先执行notifyAll 唤醒所有当前锁对象的所有wait线程,由于是第一次进入,所以没有唤醒任何线程。
  3. t1线程输出0,然后进入wait,一旦进入wait就会释放锁,此时t1线程进入WAITING状态,代码不会继续执行,而t2线程会获得锁,t2线程首先就会执行notify方法,此时t1线程被唤醒,进入BLOCK状态,然后t2线程打印1,t2线程执行wait方法,释放锁。
  4. t2线程一旦释放锁,t1线程就会拿到锁,执行完上次被wait之后的代码,然后继续进入print方法,此时t2线程不会去参与锁的竞争,因为是WAITING状态,那t1线程继续执行notifyAll,唤醒t2,t1又执行wait释放锁,t2继续执行完上次被wait后的代码,又进入方法执行,最后实现双线程交替输出。
Java线程中,waitnotifyAll是两个与线程协作相关的方法。使用synchronize获取对象的锁定后,可以使用wait方法让线程休息,通常是线程等待某个资源就绪后才能继续执行。调用wait方法时,线程必须获得锁,并且会被放入一个休息室,也被称为wait set。示例中的synchronize(this){....this.wait();....}表示在获取当前对象的锁后,在括号内的代码执行之前,线程会进入休息状态。 而notifyAll方法是通知线程,告诉它们等待的资源已经就绪了,可以去争夺资源。notifyAll会通知所有在wait set中的线程,这些线程会去竞争就绪的资源,哪个线程能够抢到资源就是运气的问题。 综上所述,wait方法是让线程等待某个资源就绪后再继续执行,而notifyAll方法是通知等待的线程资源已经就绪,可以去竞争资源。<span class="em">1</span><span class="em">2</span> #### 引用[.reference_title] - *1* [wait notifyall用户实例](https://download.csdn.net/download/dev_hwh818/3487469)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [java wait notifyAll方法](https://blog.csdn.net/xly_971223/article/details/84436705)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值