我有两个主线程。一个产生新线程,另一个产生结果,如下所示:
//Spawner
while(!done) {
spawnNewProcess(nextId, parameters);
myListener.listenFor(nextId);
nextId ++;
}
spawnNewProcess方法需要大量可变的时间。完成后,它会将结果对象放入可由Id访问的地图中。
侦听器线程运行如下:
//Listener
while(!done) {
for (int id : toListenFor) {
if (resultMap.contains(id)) {
result = resultMap.get(id);
toListenFor.remove(id);
process(result);
}
}
}
我无法更改spawnNewProcess方法,也无法更改结果的存储方式。我想要做的是设置一个可以同时进行的最大限制。我的第一个倾向是只有一个可变曲目的数字。如果超过最大值,则生成器等待。当结果返回时,监听器将通知它。像这样:
//Spawner2
AtomicInteger numSpawns = new AtomicInteger(0);
int maxSpawns = 10;
while(!done) {
if (numSpawns.intValue() >= maxSpawns) {
this.wait(0);
}
numSpawns.getAndIncrement;
spawnNewProcess(nextId, parameters);
myListener.listenFor(nextId);
nextId ++;
}
听众是:
//Listener2
while(!done) {
for (int id : toListenFor) {
if (resultMap.contains(id)) {
result = resultMap.get(id);
toListenFor.remove(id);
numSpawns.getAndDecrement();
Spawner.notify();
process(result);
}
}
}
这会有用吗?是否存在我错过的潜在僵局?如果不知何故11或9个生成器同时运行而不是10个,那将不会是一个大问题。还是有一个更好的方式,我没有注意到?
答案 0 :(得分:2)
使用Semaphore
。
import java.util.concurrent.Semaphore;
private Semaphore sem = new Semaphore(NUM_MAX_CONCURRENT);
// Spawner
while(!done) {
sem.acquire(); // added by corsiKa
spawnNewProcess(nextId, parameters);
myListener.listenFor(nextId);
nextId ++;
}
// listener
while(!done) {
for (int id : toListenFor) {
if (resultMap.contains(id)) {
result = resultMap.get(id);
toListenFor.remove(id);
sem.release(); // added by corsiKa
process(result);
}
}
}
答案 1 :(得分:0)
要控制正在运行的生成器的数量,请使用Executors.newFixedThreadPool(size)
,它将始终运行不超过固定数量的任务。然后将产卵任务包装在Runnable
中并将其传递给ExecutorService
。
while(!done) {
task = new Runnable() { public void run() {
spawnNewProcess(nextId, parameters);
} });
exec.submit(task);;
nextId ++;
}
要获得结果,请使用SynchronousQueue
或ConcurrentLinkedQueue
,这将允许您在线程之间传递对象,而不使用较低级别的并发对象。