Java

wait()、notify()、notifyAll()

2019-07-03  本文已影响0人  刘一一同学

1. 概述

wait()、notify()、notifyAll() 适应于生产者和消费者场景,结合synchronized使用。

2. 实现原理

wait()

wait()方法为Object对象的方法,执行该方法之前, 必须先获得锁。执行该方法后,会释放锁,使线程等待,进入阻塞队列。

notify()

notify()默认的唤醒策略是:先进入wait()的线程先被唤醒。

notifyAll()

notifyAll()唤醒所有的等待线程,默认的唤醒策略是:LIFO(后进先出)。

3. 集合WaitSet和EntrySet

JVM会为每一个使用内部锁(synchronized)的对象维护着两个集合:WaitSetEntrySet (抢锁机制)

4. 集合中的线程在什么条件下可以转变为Runnable状态?

5. 为什么wait()方法要在循环中调用?

首先,没有规定说必须要放在while循环,至于放在哪是根据要实现的逻辑决定的。

一般来说,wait()肯定是在触发某个条件时调用的,不是if就是while。放在while里面是防止处于Wating的线程被唤醒后,while里面的条件并没有满足(也有可能当时满足了,但是由于别的线程操作之后,又不满足了),这时就需要再次调用wait()进入阻塞队列,等待下次被唤醒。

6. 为什么wait()、notify()和notifyAll()要与synchronized一起使用?

有synchronized的地方不一定有wait()和notify(),但有wait()和notify()的地方必有synchronized,这是因为wait()和notify()不属于线程类,而是每一个对象都具有的方法。而且,这两个方法都和对象锁有关,有锁的地方,必须有synchronized

7. 为什么wait()、notify()和notifyAll()这些方法不在thread类里面?

简单的说,由于wait()、notify()和notifyAll()都是锁级别的操作,所以把他们定义在Object类中,因为锁属于对象。

8. 使用示例

public class ProducerConsumer {
    public static void main(String args[]) {
        Queue<Integer> queue = new LinkedList<>();
        Thread producer = new Producer(queue);
        Thread consumerA = new ConsumerA(queue);
        Thread consumerB = new ConsumerB(queue);
        producer.start();
        consumerA.start();
        consumerB.start();
    }
}

/**
 * Producer
 */
class Producer extends Thread {
    private Queue<Integer> queue;
    public Producer(Queue<Integer> queue) {
        this.queue = queue;
    }
    @Override
    public void run() {
        while (true) {
            synchronized (queue) {
                while (!queue.isEmpty()) {
                    try {
                        queue.wait();
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                }
                Random random = new Random();
                int i = random.nextInt();
                System.out.println("生产数据: " + i);
                queue.add(i);
                // queue.notify();
                queue.notifyAll();
            }
        }
    }
}

/**
 * Consumer
 */
class ConsumerA extends Thread {
    private Queue<Integer> queue;
    public ConsumerA(Queue<Integer> queue) {
        this.queue = queue;
    }
    @Override
    public void run() {
        while (true) {
            synchronized (queue) {
                while (queue.isEmpty()) {
                    try {
                        queue.wait();
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                }
                System.out.println("消费数据A: " + queue.remove());
                queue.notifyAll();
            }
        }
    }
}

class ConsumerB extends Thread {
    private Queue<Integer> queue;
    public ConsumerB(Queue<Integer> queue) {
        this.queue = queue;
    }
    @Override
    public void run() {
        while (true) {
            synchronized (queue) {
                while (queue.isEmpty()) {
                    try {
                        queue.wait();
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                }
                System.out.println("消费数据B: " + queue.remove());
                queue.notifyAll();
            }
        }
    }

}
上一篇 下一篇

猜你喜欢

热点阅读