使用Synchroniazed、wait、notify()实现
代码如下:
public class Test {
private static int count = 10;
private static Object lock = new Object();
public static void main(String[] args) {
Test test = new Test();
Producer producer = test.new Producer();
Consumer consumer = test.new Consumer();
producer.start();
consumer.start();
}
class Consumer extends Thread{
@Override
public void run() {
consume();
}
private void consume() {
while(true){
synchronized (lock) {
while(count == 0){
try {
System.out.println("队列空,等待数据");
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
lock.notify();
}
}
count--; //每次移走队首元素
lock.notify();
System.out.println("从队列取走一个元素,队列剩余"+count+"个元素");
}
}
}
}
class Producer extends Thread{
@Override
public void run() {
produce();
}
private void produce() {
while(true){
synchronized (lock) {
while(count == 10){
try {
System.out.println("队列满,等待有空余空间");
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
lock.notify();
}
}
count++; //每次插入一个元素
lock.notify();
System.out.println("向队列取中插入一个元素,队列剩余空间:"+10-count));
}
}
}
}
}
我们知道 notify()方法唤醒线程,只能唤醒唤醒一个线程,那如果有多个生产者多个消费者,当队列满时,调用lock.notify()的时候,就不确定唤醒的是生产者还是消费者了。
这个问题使用condition就比较好解决。
使用Lock和Condition实现生产者消费者
public class Test {
private static int count = 10;
private Lock lock = new ReentrantLock();
private Condition notFull = lock.newCondition();
private Condition notEmpty = lock.newCondition();
public static void main(String[] args) {
Test test = new Test();
Producer producer = test.new Producer();
Consumer consumer = test.new Consumer();
producer.start();
consumer.start();
}
class Consumer extends Thread{
@Override
public void run() {
consume();
}
private void consume() {
while(true){
lock.lock();
try {
while(count == 0){
try {
System.out.println("队列空,等待数据");
notEmpty.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
count--; //每次移走队首元素
notFull.signal(); //指定唤醒生产者
System.out.println("从队列取走一个元素,队列剩余"+count+"个元素");
} finally{
lock.unlock();
}
}
}
}
class Producer extends Thread{
@Override
public void run() {
produce();
}
private void produce() {
while(true){
lock.lock();
try {
while(count == 10){
try {
System.out.println("队列满,等待有空余空间");
notFull.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
count++; //每次插入一个元素
notEmpty.signal(); //制定唤醒消费者
System.out.println("向队列取中插入一个元素,队列剩余空间:"+(10-count));
} finally{
lock.unlock();
}
}
}
}
}
这就是多个Condition的强大之处,假设队列中已经存满,那么阻塞的肯定是写线程,唤醒的肯定是读线程,相反,阻塞的肯定是读线程,唤醒的肯定是写线程。