Java并发在实践中的应用&x201C;清单12.5。BoundedBuffer和#x201D的生产者-消费者测试计划;循环障碍有待理解?
我在实践中阅读Java并发性,并遇到以下代码片段。 清单12.5Java并发在实践中的应用&x201C;清单12.5。BoundedBuffer和#x201D的生产者-消费者测试计划;循环障碍有待理解?,java,multithreading,concurrency,Java,Multithreading,Concurrency,我在实践中阅读Java并发性,并遇到以下代码片段。 清单12.5 //清单12.5。BoundedBuffer的生产者-消费者测试程序。 包net.jcip.examples; 导入java.util.concurrent.*; 导入java.util.concurrent.atomic.*; 导入junit.framework.TestCase; /** *推杆试验 * *BoundedBuffer的生产者-消费者测试程序 * *@作者Brian Goetz和Tim Peierls */ 公共
//清单12.5。BoundedBuffer的生产者-消费者测试程序。
包net.jcip.examples;
导入java.util.concurrent.*;
导入java.util.concurrent.atomic.*;
导入junit.framework.TestCase;
/**
*推杆试验
*
*BoundedBuffer的生产者-消费者测试程序
*
*@作者Brian Goetz和Tim Peierls
*/
公共类PutTakeTest扩展了TestCase{
受保护的静态最终执行器服务池=Executors.newCachedThreadPool();
受保护的循环载体屏障;
受保护的最终信号量BoundedBuffer bb;
受保护的最终国际文件、NPAIR;
受保护的最终AtomicInteger putSum=新的AtomicInteger(0);
受保护的最终AtomicInteger takeSum=新的AtomicInteger(0);
公共静态void main(字符串[]args)引发异常{
new PutTakeTest(10,10,100000).test();//示例参数
pool.shutdown();
}
公共推杆测试(int容量、int NPAIR、int NTRIAL){
this.bb=新信号量BoundedBuffer(容量);
this.nTrials=nTrials;
this.nPairs=nPairs;
此.barrier=新循环载体(npairs*2+1);
}
无效测试(){
试一试{
对于(int i=0;i>21);
y^=(y 0;--i){
把(种子);
总和+=种子;
种子=xorShift(种子);
}
putSum.getandad(sum);
障碍。等待();
}捕获(例外e){
抛出新的运行时异常(e);
}
}
}
类使用者实现Runnable{
公开募捐{
试一试{
障碍。等待();
整数和=0;
对于(int i=nTrials;i>0;--i){
sum+=bb.take();
}
takeSum.getandad(sum);
障碍。等待();
}捕获(例外e){
抛出新的运行时异常(e);
}
}
}
}
我发现很难理解如何在主线程或可运行线程中第二次调用循环屏障。根据我的理解,循环屏障将阻塞线程,直到在所有线程上调用wait并且屏障计数与构造函数中传递的值匹配为止。当线程上第一次等待屏障时,循环屏障中的等待计数将是所需值(npairs*2+1)的一半。控件如何在生产者和消费者中执行put sum和take sum计算,以及如何在主线程上连续执行
如果这个问题听起来很幼稚,请提前道歉。在呼叫
等待
障碍之前,主线程启动npairs
生产者和npairs
消费者。每个if生产者和消费者调用等待
,因此它与一个主线程一起允许所有线程通过屏障。感谢您的澄清。我对Consumer类中的代码片段感到困惑。如果在run方法的第一行调用barrier await(),那么在同一方法中如何第二次调用barrier。使用者线程何时激活以在run方法中调用barrier wait第二次?public void run(){try{barrier.await();int sum=0;//计算和逻辑barrier.await();}catch(异常e){}当所有线程首先到达等待时,它们都会通过屏障并开始执行后续工作。然后他们到达第二个等待
,当所有线程都在那里时,他们继续通过它并计算最终结果。当第一个等待在所有线程上调用并且线程开始计算总和时,循环屏障是否重置回线程数目的计数?是,我想Java Concyrency在实践中也提到了这一点,非常感谢!我不知怎的错过了周期性障碍物的重置。
// Listing 12.5. Producer-consumer test program for BoundedBuffer.
package net.jcip.examples;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
import junit.framework.TestCase;
/**
* PutTakeTest
* <p/>
* Producer-consumer test program for BoundedBuffer
*
* @author Brian Goetz and Tim Peierls
*/
public class PutTakeTest extends TestCase {
protected static final ExecutorService pool = Executors.newCachedThreadPool();
protected CyclicBarrier barrier;
protected final SemaphoreBoundedBuffer<Integer> bb;
protected final int nTrials, nPairs;
protected final AtomicInteger putSum = new AtomicInteger(0);
protected final AtomicInteger takeSum = new AtomicInteger(0);
public static void main(String[] args) throws Exception {
new PutTakeTest(10, 10, 100000).test(); // sample parameters
pool.shutdown();
}
public PutTakeTest(int capacity, int npairs, int ntrials) {
this.bb = new SemaphoreBoundedBuffer<Integer>(capacity);
this.nTrials = ntrials;
this.nPairs = npairs;
this.barrier = new CyclicBarrier(npairs * 2 + 1);
}
void test() {
try {
for (int i = 0; i < nPairs; i++) {
pool.execute(new Producer());
pool.execute(new Consumer());
}
barrier.await(); // wait for all threads to be ready
barrier.await(); // wait for all threads to finish
assertEquals(putSum.get(), takeSum.get());
} catch (Exception e) {
throw new RuntimeException(e);
}
}
static int xorShift(int y) {
y ^= (y << 6);
y ^= (y >>> 21);
y ^= (y << 7);
return y;
}
class Producer implements Runnable {
public void run() {
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 = xorShift(seed);
}
putSum.getAndAdd(sum);
barrier.await();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
class Consumer implements Runnable {
public void run() {
try {
barrier.await();
int sum = 0;
for (int i = nTrials; i > 0; --i) {
sum += bb.take();
}
takeSum.getAndAdd(sum);
barrier.await();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}