Java 带可运行共享循环传送器的ExecutorService
我在Java中的并发解决方案中遇到了一个问题,它使用了一个共享Java 带可运行共享循环传送器的ExecutorService,java,multithreading,executorservice,cyclicbarrier,Java,Multithreading,Executorservice,Cyclicbarrier,我在Java中的并发解决方案中遇到了一个问题,它使用了一个共享CyclicBarrier的n Runnable类,并且Runnable由ExecutorService处理,下面是代码: public class Worker implements Runnable { private CyclicBarrier writeBarrier; private int index; private int valuetocalculate; public Worker(int
CyclicBarrier
的n Runnable类,并且Runnable
由ExecutorService
处理,下面是代码:
public class Worker implements Runnable {
private CyclicBarrier writeBarrier;
private int index;
private int valuetocalculate;
public Worker(int i,CyclicBarrier writeBarrier)
{
this.writeBarrier = writeBarrier;
this.index = i;
this.valuetocalculate = 0;
}
public void run() {
//calculations with valuetocalculate
writeBarrier.await();
//write new valuetocalculate value
}
}
public class Context {
private ArrayList<Worker> workers;
private Chief chief;
public Context()
{
workers = new ArrayList<Worker>();
chief = new Chief();
}
public void generateRandomWorkers(nworkers)
{
writeBarrier = newWriteBarrier(workers);
chief.setBarrier(writeBarrier);
//generate random woker
for (int i = 0; i<nworkers;i++)
{
Worker worker = new Worker(i,writeBarrier);
workers.add(worker);
}
chief.setWorkersArray(workers);
chief.start();
}
}
public class Chief extend Thread {
private CyclicBarrier writeBarrier;
private ArrayList<Worker> workers;
private ExecutorService executor;
private int cores;
public Chief ()
{
cores = Runtime.getRuntime().availableProcessors()+1;
}
public void setBarrier (CyclicBarrier writeBarrier)
{
this.writeBarrier = writeBarrier;
}
public setWorkersArray(ArrayList<Worker> workers)
{
this.workers = workers;
}
public ArrayList<Integer> getvaluetocalculate()
{
ArrayList<Integer> values = new ArrayList<Integer> ();
for (int i = 0; i<workers.size();i++)
{
values.add(workers.get(i).valuetocalculate);
}
return values;
}
public void run(){
while (!stop) //always true for testing
{
getvaluetocalculate();
//make calculations
writeBarrier.reset();
executor = Executors.newFixedThreadPool(cores);
for (int i = 0;i<workers.size();i++)
{
Runnable runnable = workers.get(i);
executor.execute(runnable);
}
executor.shutdown();
while (!executor.isTerminated())
{
}
}
}
}
问题是Runnable
在Chief
的运行中没有经过第一次“迭代”,因此问题似乎是工作人员没有经过writerbrier.await()代码>,如果我初始化了它:
executor = Executors.newFixedThreadPool(cores);
使用workers.size()
,可以工作,但似乎不同步……我如何解决呢?好,看来您正在尝试执行以下操作
- 一名负责控制工人的主管/调度员
- 一名或多名工人正在进行计算
- 主任处决所有工人
- 主任等待所有工人完成工作
- 主管从每个工人那里获取结果以计算结果
假设以上是你的问题
- 在worker run()方法中执行barrier.await()可以防止将该线程释放回池以运行后续worker。因此,当池大小<工作线程大小时,第一个“池大小”工作线程消耗线程,然后停止等待其他无法运行的线程。这就是为什么除非将池大小更改为workers.size(),否则并非所有的worker都会运行
valuetocalculate
变量在设置结果的工作人员和读取结果的主管之间不同步,因此您可能会看到过时的结果
实现此类系统的正确方法是让工作人员实现Callable,其中Callable在工作人员计算后返回结果。这负责将结果发布回您的主管(您将在下面看到这是如何工作的)
移除循环屏障,你不需要它
按现在的样子创建执行器,并使用可调用项列表(您的工作人员)调用invokeAll()
。此方法使用执行器调用可调用项,并等待它们完成。它将阻塞,直到所有工作人员都完成,此时它将返回一个列表。每个Future对应于您传入的一个Worker/Callable。迭代列表,将结果拉出来。如果工作进程尝试get()
失败,则其未来的结果将抛出异常
希望这会有所帮助。为什么您认为它不同步?我已检查并已同步,但我更喜欢根据处理器的数量划分线程,因此请使用che-ncoresthank。非常感谢您所描述的问题!但是我如何使用执行器与可用线程一起工作?
executor = Executors.newFixedThreadPool(cores);