import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
/**
* 有四个生产者线程A、B、C、D,分别向一个固定大小为11的storage数组(int storage[]=new int[15];)中插入数据。
* 线程A只能插入数字1,线程B只能插入数字2,线程C只能插入数字3,线程D只能插入数字4,插入的数字顺序为1,2,3,4,1,2,3,4,1……。
* 同时有一个消费者线程E从storage数组中取出数字(每次取一个,取出来之后就打印这个数字)。
* 要求打印数字的顺序为插入顺序(每个线程插入100次各自的数字),完成全部入库出库操作耗时控制在200毫秒以内。
* @author user
*
*/
public class App {
public static AtomicInteger state = new AtomicInteger(0); //用来保证生产顺序的状态量
public static int[] storage = new int[11]; //生产线
public static AtomicInteger currentStorageIndex = new AtomicInteger(0); //生产线指针
public static ReentrantLock syncLock = new ReentrantLock(false); //用来保证消费者消费与生产者生产进行同步的lock
public static Condition consumeCondition = syncLock.newCondition(); //消费者同步信号量
public static Condition productCondition = syncLock.newCondition(); //生产者同步信号量
public static CountDownLatch latch = new CountDownLatch(5); //用来监视所有生产者线程是否执行完毕的latch
//消费者
public static class Consumer implements Runnable {
public AtomicBoolean isStarted = new AtomicBoolean(false);
@Override
public void run() {
while (latch.getCount() > 0) {
try {
isStarted.set(true);
syncLock.lock();
//等待生产线变满
consumeCondition.await();
for (int i = 0; i < storage.length; i++) {
if (storage[i] != 0) {
System.out.print(storage[i]);
storage[i] = 0;
}
}
//重置生产线指针
currentStorageIndex.set(0);;
productCondition.signalAll();
} catch (InterruptedException e) {
} finally {
syncLock.unlock();
}
}
}
}
//生产者
public static class Productor implements Runnable {
public int expect; //前置量,状态为该值,才会加入生产线
public int number; //生产量,即加入生产线的量,生产完毕会将状态量设置为该量
public int repeat; //重试次数
@Override
public void run() {
while (repeat > 0) {
int currentState = state.get();
if (expect == currentState) {
//双重校验
if (state.get() == currentState) {
try {
syncLock.lock();
//CAS,保证多线程环境下的state并发修改的happends-before(1,2,3,4,0顺序)
if (state.compareAndSet(expect, number)) {
int index = currentStorageIndex.incrementAndGet();
if (index >= storage.length) {
if(index == storage.length + latch.getCount() - 1){
//此时所有生产者会处于停滞状态,需要启动通知消费者进行消费
consumeCondition.signalAll();
}
//等待消费者消费
productCondition.await();
} else {
repeat--;
storage[index] = expect;
}
}
} catch (InterruptedException e) {
} finally {
syncLock.unlock();
}
}
} else {
Thread.yield();
}
}
latch.countDown();
}
public Productor(int expect, int number, int repeat) {
this.expect = expect;
this.number = number;
this.repeat = repeat;
}
}
public static void main(String[] args) throws InterruptedException {
long sartTime = System.currentTimeMillis();
//构造生产者实例
Productor p1 = new Productor(0, 1, 100);
Productor p2 = new Productor(1, 2, 100);
Productor p3 = new Productor(2, 3, 100);
Productor p4 = new Productor(3, 4, 100);
Productor monitor = new Productor(4, 0, 100);
//构造所有消费者实例
Consumer consumer = new Consumer();
//创建并启动消费者线程
Thread tConsumer = new Thread(consumer);
tConsumer.start();
//等待消费者启动完毕
while (!consumer.isStarted.get()) {
Thread.yield();
}
//启动所有生产者
new Thread(p1).start();
new Thread(p2).start();
new Thread(p3).start();
new Thread(p4).start();
new Thread(monitor).start();
//等待生产者执行完毕
latch.await();
//让消费者进行最后一次消费
syncLock.lock();
consumeCondition.signalAll();
syncLock.unlock();
//等待消费者执行完毕
tConsumer.join();
long endTime = System.currentTimeMillis();
System.out.println("\n执行完毕,耗时 " + (endTime - sartTime) + "ms.");
}
}
转载于:https://blog.51cto.com/12222886/1963898