0

2 つのプライマリ スレッドがあります。1 つは新しいスレッドを生成し、もう 1 つは次のように結果をリッスンします。

//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);
        }
    }
}

これは機能しますか?私が見逃している潜在的なデッドロックはありますか? どういうわけか、10 ではなく 11 または 9 のスポーンが同時に実行されていたとしても、それは大したことではありません。

4

2 に答える 2

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);
        }
    }
}
于 2013-03-01T18:51:27.333 に答える
0

実行中の spawner の数を制御するには、 を使用しますExecutors.newFixedThreadPool(size)。これは常に、一度に実行されるタスクの数が固定数を超えないようにします。次に、スポーン タスクを でラップし、Runnableに渡しますExecutorService

while(!done) {
    task = new Runnable() { public void run() {
        spawnNewProcess(nextId, parameters);
    } });

    exec.submit(task);;

    nextId ++;
}

結果を取得するには、SynchronousQueueまたはConcurrentLinkedQueueを使用します。これにより、低レベルの同時実行オブジェクトを使用せずにスレッド間でオブジェクトを渡すことができます。

于 2013-03-01T18:59:55.327 に答える