packagecn.study.concurrency.ch12;importjava.util.concurrent.CyclicBarrier;importjava.util.concurrent.ExecutorService;importjava.util.concurrent.Executors;importjava.util.concurrent.atomic.AtomicInteger;public classPutTakeTest {//创建线程池
private static final ExecutorService pool =Executors.newCachedThreadPool();//原子型的int数据,最后用来统计线程设计是否合理,是否线程安全
private final AtomicInteger putSum = new AtomicInteger(0);private final AtomicInteger takeSum = new AtomicInteger(0);private final CyclicBarrier barrier; //栅栏
private final BoundedBuffer bb; //队列
private final int nTrials, nPairs; //要创建的队列数量和栅栏的屏障点//构造函数
public PutTakeTest(int capacity, int npairs, intntrials) {this.bb = new BoundedBuffer(capacity);this.nTrials =ntrials;this.nPairs =npairs;//+1是为了,在所有的线程都建立结束之后,最后编码手动决定什么时候启动所有线程
this.barrier = new CyclicBarrier(2 * npairs + 1);
}//生产者线程
class Producer implementsRunnable
{
@Overridepublic voidrun() {try{//设计随机种子,异或操作
int seed = (this.hashCode() ^ (int)System.nanoTime());int sum = 0;
barrier.await();//进行栅栏等待
for(int i = nTrials; i > 0; --i)
{
bb.put(seed);
sum+=seed;
seed= Util.xorShift(seed);//获取随机值
}//获取值,并且添加到putsum中
putSum.getAndAdd(sum);
barrier.await();//添加一个栅栏,标识运行结束
} catch(Exception e) {
System.out.println("????producer");
}
}
}//消费者线程
class Consumer implementsRunnable
{
@Overridepublic voidrun() {try{
barrier.await();//进行栅栏等待
int sum = 0;for(int i = nTrials; i > 0; --i)
{
sum+=bb.take();
}//获取值,并且添加到putsum中
takeSum.getAndAdd(sum);
barrier.await();//添加一个栅栏,标识运行结束
} catch(Exception e) {
e.printStackTrace();
System.out.println(Thread.currentThread().getName()+ "????consumer");
}
}
}//测试函数
public voidtest()
{try{for(int i = 0; i < nPairs; ++i)
{
pool.execute(newProducer());
pool.execute(newConsumer());
}//当现场全部添加好了之后,打开栅栏
barrier.await(); //第2n+1个//然后线程执行之后,每个线程执行完又调用了一次await,当所有的都执行完了之后
barrier.await();//全部结束之后判断是否结果对等
if(putSum.get() ==takeSum.get())
{
System.out.println("程序是OK的");
}else{
System.out.println("程序有安全漏洞");
}
}catch(Exception e) {
System.out.println("????test");
}
}public static voidmain(String[] args) {//队列容量是10,每个线程起10个,一共放100000个数据
new PutTakeTest(10, 2, 100).test();
pool.shutdown();//执行完,结束线程
}
}