使用ReentrantLock与Condition实现生产者消费者
主要有Producer,Consumer,Pool 生产池
在测试多线程程序时,最后【多建线程】才能明显看出并发时,是否数据异常。建议10到30个线程
创建的线程数少,模拟的延时太高,多线程可能会依次执行,不能判断是否线程安全
Pool生产池,封装也生产与消费的方法,注意里面的【while循环】判断Pool是否满或者空,负责会产出线程安全,过满或负数超消费问题
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.LockSupport;
import java.util.concurrent.locks.ReentrantLock;
/**
* @author zhanghui
* @date 2019/5/10
*/
public class ProducerConsumerSolutionUsingLock {
public static void main(String[] args) {
Pool pool = new Pool();
for(int i=0;i<30;i++){
Producer p = new Producer(pool);
p.setName("p"+i);
p.start();
}
for(int i=0;i<20;i++){
Consumer c = new Consumer(pool);
c.setName("c"+i);
c.start();
}
}
}
// share object
class Pool{
private int capacity=200;
private int goods=0;
private final ReentrantLock lock = new ReentrantLock(true);
private final Condition plock = lock.newCondition(); //Producer lock
private final Condition clock = lock.newCondition(); //Consumer lock
public void produceGoods(int newGoods) {
lock.lock();
try {
while (goods+newGoods>=capacity){
System.out.println("full:"+Thread.currentThread().getName());
plock.await();
}
int before = goods;
goods+=newGoods;
System.out.println("Producer:"+Thread.currentThread().getName()+" before "+before+",after "+goods);
clock.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
public void consumeGoods(int oldGoods) {
lock.lock();
try {
while(goods-oldGoods<=0){
System.out.println("empty:"+Thread.currentThread().getName());
clock.await();
}
int before = goods;
goods-=oldGoods;
System.out.println("Consumer:"+Thread.currentThread().getName()+" before "+before+",after "+goods);
plock.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}
}
}
class Producer extends Thread {
private Pool pool;
public Producer(Pool pool){
this.pool=pool;
}
@Override
public void run() {
while (true){
pool.produceGoods(5);
LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(3));
}
}
}
class Consumer extends Thread {
private Pool pool;
public Consumer(Pool pool){
this.pool=pool;
}
@Override
public void run() {
while (true){
pool.consumeGoods(3);
LockSupport.parkNanos(TimeUnit.SECONDS.toNanos(2));
}
}
}