0

この質問は、Java並行処理トピックの宿題に関連しています。私は、新しいスレッドを生成し、与えられたもので制限することを任されていますconcurrencyFactor。つまり、アクティブなスレッドの数がconcurrencyFactor以下になるまで、新しいスレッドをディスパッチしてください。アクティブなスレッドの数がconcurrencyFactorに等しい場合、プログラムはアクティブなスレッドの数がconcurrencyFactor - 1に減少するまで待機し、新しいスレッドを作成します。Javaの並行性:Executorの動作を実現するためのラッチ/スレッドグループの変更

最初のアプローチとして、私はExecutorServiceを使用しており、新しい固定プールをExecutors.newFixedThreadPool(concurrencyFactor);で作成しました。私のメソッドが呼び出されるたびに、このプールに新しい実行可能ファイルを送信しています。ロジックのコードは次のとおりです。

private final ExecutorService fixedPoolExecutor = Executors.newFixedThreadPool(concurrencyFactor); 
    public void handleRequest(final RequestHandler handler) { 
    if (handler == null) throw new IllegalArgumentException("Handler cannot be null"); 
    fixedPoolExecutor.submit(new Runnable() { 
     @Override 
     public void run() { 
      handler.serviceRoutine(); 
     } 
     }); 
    } 

ここで、2番目の部分では、実行者を使用せずに同じ目標を達成するように求めています。私は
1)activeCount0になるまで、このラッチは(つまり、latch.await())待機するだろうと、countDownLatchを使用します。カウントダウンがconcurrencyFactor - 1になるまで待つだけです。
2)ThreadGroupを使用し、threadGroup.activeCount() < concurrencyFactorまでお待ちください。しかし、このアプローチの問題は、threadGroup.activeCount() < concurrencyFactorの条件が満たされるまで着信要求を待機させるにはどうすればいいですか?

private final Lock lock = new ReentrantLock(); 
    private final ThreadGroup threadGroup = new ThreadGroup("myGroup"); 
    public void handleRequest(final RequestHandler handler) { 
    if (handler == null) throw new IllegalArgumentException("Handler cannot be null"); 
    lock.lock(); 
    try { 
     while (threadGroup.activeCount() >= concurrencyFactor) { 

     } 
     Thread t = new Thread(threadGroup, new Runnable() { 
      @Override 
      public void run() { 
       handler.service(); 
      } 
     }); 
     t.start(); 
    } finally { 
     lock.unlock(); 
    }   
    } 

2番目のアプローチでは、いくつかの待機条件でループを置き換えても問題はありませんか?

新しいアプローチの上記のアプローチまたはアドバイスについてのご意見をお待ちしております。

+0

は、あなたがたCountDownLatchを使用するために割り当て力をしていますか? – bowmore

+0

いいえ、強制しません。しかし、命令は、ラッチ/スレッド/エグゼキュータを使用してこれを達成することを示唆しています。 –

+1

これはSemaphoreにとって非常に適しているようです。 – bowmore

答えて

1

Sempahoreを使用することをお勧めします。セマフォは、まだ起動が許可されているスレッドの数を表します。最初は、コンフィグレーションされた並行性係数と等しい許可を保持します。

新しいスレッドを開始する前に、handleRequestメソッドはセマフォから許可を取得する必要があります。開始されるスレッドは、完了をリリースすると再び許可する必要があります。

サンプルコード:

private final ThreadGroup threadGroup = new ThreadGroup("myGroup"); 
private final Semaphore concurrencyFactor = new Semaphore(CONCURRENCY_FACTOR); 

public void handleRequest(final RequestHandler handler) throws InterruptedException { 
    if (handler == null) throw new IllegalArgumentException("Handler cannot be null"); 

    concurrencyFactor.acquire(); // Get permit 

    Thread t = new Thread(threadGroup, new Runnable() { 
     @Override 
     public void run() { 
      try { 
       handler.service(); 
      } finally { 
       concurrencyFactor.release(); // make sure to release permit 
      } 
     } 
    }); 
    t.start(); 
} 

(あなたが可能中断とは異なる対処することをお勧めします)

+0

これは完璧に動作します。ありがとう:) –

+0

runメソッド内のtryブロックは、 'concurrencyFactor'が' service'メソッドが完了まで実行された後にのみ解放されることを保証しますか? –

+0

service()内で例外がスローされたにもかかわらず許可が解放されることを保証します – bowmore

関連する問題