第一种: Lock Condition实现生产者和消费者问题:
package eureka.server;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class MyStock {
private List<String> stock = new ArrayList();
private int size = 10;
Lock lock = new ReentrantLock();
Condition conditionA = lock.newCondition();//生产者条件
Condition conditionB = lock.newCondition();//消费者条件
//生产
public void add() {
try {
lock.lock();
//如果仓库满了
while (stock.size() > size) {
System.out.println("当前仓库已满,当前容量=" + stock.size() + ",threadName =" + Thread.currentThread().getName());
conditionA.await();
}
//生产产品
System.out.println("生产商品start,当前容量=" + stock.size() + ",threadName =" + Thread.currentThread().getName());
stock.add("product");
System.out.println("生产商品end,当前容量=" + stock.size() + ",threadName =" + Thread.currentThread().getName());
//通知消费者
conditionB.signal();
} catch (InterruptedException e) {
} finally {
lock.unlock();
}
}
public void reduce() {
try {
lock.lock();
while (stock.size() <= 0) {
System.out.println("当前仓库没有商品,容量=" + stock.size() + ",threadName =" + Thread.currentThread().getName());
conditionB.await();
}
//消费商品
System.out.println("消费商品start,当前容量=" + stock.size() + ",threadName =" + Thread.currentThread().getName());
stock.remove(0);
System.out.println("消费商品end,当前容量=" + stock.size() + ",threadName =" + Thread.currentThread().getName());
//通知生产者
conditionA.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
public static void main(String[] args) throws InterruptedException {
MyStock myStock = new MyStock();
for (int i = 0; i < 5; i++) {
Thread threadA = new PThread("" + i, myStock);
Thread threadB = new RThread("" + i, myStock);
threadB.start();
threadA.start();
}
}
}
//生产者
class PThread extends Thread {
private MyStock myStock;
public PThread(String name, MyStock myStock) {
super(name);
this.myStock = myStock;
}
@Override
public void run() {
myStock.add();
}
}
//消费者
class RThread extends Thread {
private MyStock myStock;
public RThread(String name, MyStock myStock) {
super(name);
this.myStock = myStock;
}
@Override
public void run() {
myStock.reduce();
}
}
第二种:synchronized实现生产者、消费者问题:
package eureka.server;
import java.util.ArrayList;
import java.util.List;
public class MyStock1 {
private static List<String> stock = new ArrayList<String>();
private Object lock = new Object();
private int size = 10;
//生产产品
public void add() {
synchronized (lock) {
try {
while (stock.size() == size) {
System.out.println("当前仓库已满,当前容量=" + stock.size() + ",threadName =" + Thread.currentThread().getName());
lock.wait();
}
//生产产品
System.out.println("生产商品start,当前容量=" + stock.size() + ",threadName =" + Thread.currentThread().getName());
stock.add("product");
System.out.println("生产商品end,当前容量=" + stock.size() + ",threadName =" + Thread.currentThread().getName());
//通知消费者
lock.notifyAll();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//消费产品
public void reduce() {
synchronized (lock) {
try {
while (stock.size() == 0) {
System.out.println("当前仓库没有商品,容量=" + stock.size() + ",threadName =" + Thread.currentThread().getName());
lock.wait();
}
//消费商品
System.out.println("消费商品start,当前容量=" + stock.size() + ",threadName =" + Thread.currentThread().getName());
stock.remove(0);
System.out.println("消费商品end,当前容量=" + stock.size() + ",threadName =" + Thread.currentThread().getName());
//通知生产者
lock.notifyAll();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) throws InterruptedException {
MyStock1 myStock1 = new MyStock1();
Thread threadA = new ThreadP("aa", myStock1);
Thread threadB = new ThreadR("bb", myStock1);
Thread threadC = new ThreadR("cc", myStock1);
Thread threadD = new ThreadP("dd", myStock1);
threadB.start();
threadC.start();
Thread.sleep(1000);
threadA.start();
threadD.start();
}
}
//生产者
class ThreadP extends Thread {
private MyStock1 myStock1;
public ThreadP(String name, MyStock1 myStock1) {
super(name);
this.myStock1 = myStock1;
}
@Override
public void run() {
myStock1.add();
}
}
//消费者
class ThreadR extends Thread {
private MyStock1 myStock1;
public ThreadR(String name, MyStock1 myStock1) {
super(name);
this.myStock1 = myStock1;
}
@Override
public void run() {
myStock1.reduce();
}
}
特别注意的点:用synchronized实现时,要注意库存的判断条件用while不能用if:
while (stock.size() == size) {
System.out.println("当前仓库已满,当前容量=" + stock.size() + ",threadName =" +
Thread.currentThread().getName());
lock.wait();
}
假如说有2个消费者,1个生产者,当生产者生产一个产品后,调用notifyall方法唤醒2个消费者线程,第一个消费者被唤醒消费完这一个产品后,第二个消费者也开始准备消费产品,如果用if判断条件,此时消费者不会做库存判断,直接消费产品,会导致没有产品能够消费的情况,代码会产生数组下标越界的错误,而如果用while判断,则会判断出现在的库存数量为0,会再次进入等待wait的状态;