两种实现方式都大同小异,关键在于生产与消费的动作上,一边是synchronized加锁,Object.wait()与Object.notifyAll()实现等待与唤醒,而另一边是ReentrantLock加锁,Condition实现等待与唤醒
废话不多说,直接上代码,注意使用while代替if以防止虚假唤醒
使用synchronized关键字实现
// Producer.java
/**
* @Author: x1aolone
* @Date: 2020/3/31 16:10
*/
public class Producer extends Thread {
private Resource resource;
Producer (Resource resource) {
this.resource = resource;
}
@Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
resource.produce();
}
}
}
// Consumer.java
/**
* @Author: x1aolone
* @Date: 2020/3/31 16:10
*/
public class Consumer extends Thread {
private Resource resource;
Consumer(Resource resource) {
this.resource = resource;
}
@Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
resource.consume();
}
}
}
// Resource.java
/**
* @Author: x1aolone
* @Date: 2020/3/31 16:11
*/
public class Resource {
private final int MAX_PRODUCT_NUM = 10;
private int size = 0;
public synchronized void produce () {
while (size > MAX_PRODUCT_NUM) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
size++;
System.err.println("线程" + Thread.currentThread().getName() + "生产了一个商品,当前商品数量为" + size);
notifyAll();
}
public synchronized void consume () {
while (size <=0) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
size--;
System.err.println("线程" + Thread.currentThread().getName() + "消费了一个商品,当前商品数量为" + size);
notifyAll();
}
}
// Main.java
public class Main {
public static void main(String[] args) {
Resource resource = new Resource();
new Producer(resource).start();
new Producer(resource).start();
new Producer(resource).start();
new Consumer(resource).start();
new Consumer(resource).start();
new Consumer(resource).start();
}
}
使用ReentrantLock和Condition实现
该实现方式与上面方式的不同点在于Resource类不同,Producer、Consumer、Main这三个类的代码是一样的
// Producer.java
/**
* @Author: x1aolone
* @Date: 2020/3/31 16:10
*/
public class Producer extends Thread {
private Resource resource;
Producer (Resource resource) {
this.resource = resource;
}
@Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
resource.produce();
}
}
}
// Consumer.java
/**
* @Author: x1aolone
* @Date: 2020/3/31 16:10
*/
public class Consumer extends Thread {
private Resource resource;
Consumer(Resource resource) {
this.resource = resource;
}
@Override
public void run() {
while (true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
resource.consume();
}
}
}
// Resource.java
/**
* @Author: x1aolone
* @Date: 2020/3/31 16:11
*/
public class Resource {
private final int MAX_PRODUCT_NUM = 10;
private int size = 0;
private ReentrantLock lock = new ReentrantLock();
private Condition notEmpty = lock.newCondition();
private Condition notFull = lock.newCondition();
public void produce () {
lock.lock();
try {
while (size > MAX_PRODUCT_NUM) {
notFull.await();
}
size++;
System.err.println("线程" + Thread.currentThread().getName() + "生产了一个商品,当前商品数量为" + size);
notEmpty.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public void consume () {
lock.lock();
try {
while (size <= 0) {
notEmpty.await();
}
size--;
System.err.println("线程" + Thread.currentThread().getName() + "消费了一个商品,当前商品数量为" + size);
notFull.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
// Main.java
public class Main {
public static void main(String[] args) {
Resource resource = new Resource();
new Producer(resource).start();
new Producer(resource).start();
new Producer(resource).start();
new Consumer(resource).start();
new Consumer(resource).start();
new Consumer(resource).start();
}
}