我正在尝试使用CyclicBarrier
对我来说是新的来重新实现我的并发代码。我可以不用它,但我正在对我的其他解决方案进行试验,我遇到的问题是使用以下代码出现死锁情况:
//instance variables (fully initialised elsewhere).
private final ExecutorService exec = Executors.newFixedThreadPool(4);
private ArrayList<IListener> listeners = new ArrayList<IListener>();
private int[] playerIds;
private class WorldUpdater {
final CyclicBarrier barrier1;
final CyclicBarrier barrier2;
volatile boolean anyChange;
List<Callable<Void>> calls = new ArrayList<Callable<Void>>();
class SyncedCallable implements Callable<Void> {
final IListener listener;
private SyncedCallable(IListener listener) {
this.listener = listener;
}
@Override
public Void call() throws Exception {
listener.startUpdate();
if (barrier1.await() == 0) {
anyChange = processCommons();
}
barrier2.await();
listener.endUpdate(anyChange);
return null;
}
}
public WorldUpdater(ArrayList<IListener> listeners, int[] playerIds) {
barrier2 = new CyclicBarrier(listeners.size());
barrier1 = new CyclicBarrier(listeners.size());
for (int i : playerIds)
calls.add(new SyncedCallable(listeners.get(i)));
}
void start(){
try {
exec.invokeAll(calls);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
void someMethodCalledEveryFrame() {
//Calls some Fisher-something method that shuffles int[]
shufflePIDs();
WorldUpdater updater = new WorldUpdater(listeners, playerIds);
updater.start();
}
我使用 Android Studio (intelliJ) 中的调试器在此阶段暂停执行。我得到多个线程显示我的await
调用作为我要执行的最后一个代码
->
Unsafe.park
->
LockSupport.park
->
AbstractQueuedSynchronizer$ConditionObject.await
->
CyclicBarrier.doWait
->
CyclicBarrier.await
至少一个线程将具有此堆栈:
-> Unsafe.park
。
->LockSupport.park
->AbstractQueuedSynchronizer$ConditionObject.await
->LinkedBlockingQueue.take
->ThreadPoolExecutor.getTask
->ThreadPoolExecutor.runWorker
->ThreadPoolExecutor$Worker.run
->Thread.run
我注意到CyclicBarrier
在后面的这些杂散线程中没有任何作用。
processCommons
正在调用exec.invokeAll
(在 3 个侦听器上),我想这意味着我的线程用完了。但是很多时候这并没有发生,所以请有人澄清为什么ExecutorService
不能始终如一地安排我的线程?他们有自己的堆栈和程序计数器,所以我认为这不是问题。我一次最多只能运行 4 个。有人帮我做数学吗?