0

固定数のスレッドを取得しました。Runnable各スレッドを次々に3回実行したいと思います。説明するためのいくつかの擬似コードは次のとおりです。

Thread[] threads = new Thread[4];

for (int i = 0; i < threads.length; i++) {
    // Set the first tasks.
    threads[i] = new Thread(new FirstRunnable());
    threads[i].start();
}

for (int i = 0; i < threads.length; i++)
    threads[i].join(); // wait until the first tasks are done

for (int i = 0; i < threads.length; i++) {
    // Set the second task.
    threads[i].setRunnable(new SecondRunnable());
    threads[i].start();
}

for (int i = 0; i < threads.length; i++)
    threads[i].join(); // wait until the second tasks are done

...

ThreadPool特に私がパフォーマンス、パフォーマンス、パフォーマンスに向かっているので、音を使うのはやり過ぎです。これをJavaで実装するための最良の方法は何ですか?

4

5 に答える 5

4

あなたが見るときはいつでもnew Thread(...).start()、フレームワークを利用してくださいExecutors。特に、を利用してExecutors.newFixedThreadPool(...)ください。

于 2011-06-30T11:12:33.917 に答える
1

以下に示すように、 CyclicBarrierと「CombinedRunnable」を使用できます。バリアにより、スレッドはすべて、次の実行可能ファイルに進む前に、互いに終了するのを待つことができます。

CyclicBarrier barrier = new CyclicBarrier(4);
Runnable r = new CombinedRunnable(barrier, new FirstRunnable(), new SecondRunnable());
Thread[] threads = new Thread[4];
for (int i = 0; i < threads.length; i++) {
    threads[i] = new Thread(r);
    threads[i].start();
}

CombinedRunnableクラス:

public class CombinedRunnable implements Runnable{

    private final CyclicBarrier barrier;
    private final Runnable[] runnables;

    public CombinedRunnable(CyclicBarrier barrier, Runnable... runnables){
        this.barrier = barrier;
        this.runnables = runnables;
    }

    /* (non-Javadoc)
     * @see java.lang.Runnable#run()
     */
    @Override
    public void run() {
        for(Runnable r: runnables){
            r.run();
            try {
                barrier.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (BrokenBarrierException e) {
                e.printStackTrace();
            }
        }
    }
}
于 2011-06-30T11:14:27.307 に答える
1

ExecutorsクラスのnewFixedThreadPoolの良い使い方のようです。

したがって、コードは次のようになります。

ExecutorService es = Executors.newFixedThreadPool(4);
List<Future> futures = new ArrayList<Future>();
for (int x = 0; x < 4; x ++) {
    futures.add(es.submit(new FirstRunnable()));
}
while (futures.size() > 0) {
   futures.remove(0).get();
}
for (int x = 0; x < 4; x ++) {
    futures.add(es.submit(new SecondRunnable()));
}

while (futures.size() > 0) {
   futures.remove(0).get();
}

もちろん、上記のコードを簡単にリファクタリングして、コードの重複を取り除くこともできます。

于 2011-06-30T11:17:29.627 に答える
0

これを実現する慣用的な方法は、をExecutorと組み合わせて使用​​することCompletionServiceです。これにより、多くの作業単位を固定サイズのスレッドプールにマップでき、すべての作業が完了するまでブロックするための洗練されたメカニズムも提供されます。

スレッドプールの使用が効率にどのように影響するかについての懸念は実際には問題ではないことに注意してください。主なオーバーヘッドは、とにかく行っていた個々のスレッドの作成にあります。プールを作成する際の追加のオブジェクト作成オーバーヘッドはごくわずかです。

// Create fixed thread pool and wrap in a CompletionService to allow for easy access to completed tasks.
// We don't have an explicit result for each Runnable so parameterise the service on Void.
CompletionService<Void> cs = new ExecutorCompletionService<Void>(Executors.newFixedThreadPool(3));

// Create units of work for submission to completion service.
Runnable[] runnables = ...

// Submit runnables.  Note that we don't care about the result so pass in null.
for (Runnable r : runnables) {
  cs.submit(r, null);
}

// Take each *completed* result in turn, blocking until a completed result becomes available.
for (int i=0; i<runnables.length; ++i) {
  Future<Void> completed = cs.take();
}
于 2011-06-30T11:47:28.640 に答える
-2

ExecutorFrameworkはあなたにぴったりです。
擬似コードは次のとおり
です。1。エグゼキュータサービスを作成します

Executors type1Runnables = Executors.newFixedThreadPool(4);
Executors type2Runnables = Executors.newFixedThreadPool(4);

など
。2。タスクを送信します

for(){
type1Runnables.submit(new Runnable1());
type2Runnables.submit(new Runnable2);
}

3.エグゼキュータを呼び出します

type1Runnables.invokeAll();
type2Runnables.invokeAll();

より一般的にするために、さまざまな実行可能なタイプを受け入れる独自のexecutorservicefactoryを作成することができます。

于 2011-06-30T11:17:25.130 に答える