双线程利用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后的代码,又进入方法执行,最后实现双线程交替输出。

猜你喜欢

转载自blog.csdn.net/qq_43750656/article/details/132220813