还记得前面用ArrayList实现阻塞队列的文章:《 什么?面试官让我用ArrayList实现一个阻塞队列?》。我们通过synchronized并配合wait和notify实现了一个阻塞队列。在介绍完前文的synchronized关键字的基本使用之后,本文来对这些方法进行分析。
1.生产者和消费者模型
Producer代码如下:
public class Producer implements Runnable {
List<Integer> cache;
public Producer(List<Integer> cache) {
new Object();
this.cache = cache;
}
public void put() throws InterruptedException {
synchronized (cache) {
System.out.println(Thread.currentThread().getName()+"获得锁");
cache.notify();
while (cache.size() == 1) {
try {
System.out.println(Thread.currentThread().getName()+"wait");
cache.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
TimeUnit.SECONDS.sleep(1);
cache.add(1);
System.out.println(Thread.currentThread().getName() + "生产者写入1条消息");
}
}
@Override
public void run() {
while (true) {
try {
put();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Consumer代码如下:
public class Consumer implements Runnable {
List<Integer> cache;
public Consumer(List<Integer> cache) {
this.cache = cache;
}
private void consumer() {
synchronized (cache) {
System.out.println(Thread.currentThread().getName()+"获得锁");
cache.notify();
while (cache.size() == 0) {
try {
System.out.println(Thread.currentThread().getName()+"wait");
cache.wait();
}catch (InterruptedException e) {
e.printStackTrace();
}
}
cache.remove(0);
System.out.println(Thread.currentThread().getName()+" 消费者消费了1条消息");
}
}
@Override
public void run() {
while (true) {
consumer();
}
}
}
我们来调用上述的生产者和消费者模型:
public static void main(String[] args) {
List<Integer> cache = new ArrayList<>();
new Thread(new Producer(cache),"P1").start();
new Thread(new Consumer(cache),"C1").start();
}
启用了两个线程,分别调用生产者和消费者,可以看到这个过程交替执行:
P1获得锁
P1生产者写入1条消息
P1获得锁
P1wait
C1获得锁
C1 消费者消费了1条消息
C1获得锁
C1wait
P1生产者写入1条消息