3

スレッド プールの設計パターンの恩恵を受けるタスクがあります (多数の小さなタスクを並行して実行する必要があります)。私は最初に単純なスレッド プールをゼロから実装しました。n 個の Runnables はすべてConcurrentLinkedQueue、キューが空になるまでワーク ユニットをプルし、終了します。次に、「ねえ、Java で Executor を試してみましょう。私の素朴に設計されたシステムよりも、おそらくより適切にテストされ、信頼性が高いからです」と決めました。問題: 私の実装では、各スレッドは while を使用してキューが空になるまで存続し(!queue.isEmpty())、非スレッドセーフ オブジェクトの独自のインスタンスを取得しましたSlowObject fooRunnableのプールに入るすべての を渡そうとするExecutorと、時間効率の悪いオブジェクトのインスタンスがスレッドセーフではないため失敗します。SlowObjectfor eachRunnableは構築にコストがかかるため望ましくありません。

SlowObject「使用しているスレッドの数は?スレッドごとに 1 つ作成し、実行中のスレッドを Runnables に検出させて、使用する正しいオブジェクトを検索させましょう?」と言う方法はありますか? これは脆弱で失敗しやすいように思えますが、代わりにどのデザイン パターンを調べればよいかわかりません。

4

2 に答える 2

4

リソース プールを使用することをお勧めします。次のようなものを使用します。

public class SlowObjectPool {
    private static final int POOL_SIZE = 10;
    private BlockingQueue<SlowObject> slowObjectQueue = new ArrayBlockingQueue(POOL_SIZE);

    public SlowObjectPool() {
        for (int i = 0; i < POOL_SIZE; i++) {
            slowObjectQueue.put(new SlowObject());
        }
    }

    public SlowObject take() throws InterruptedException {
        return slowObjectQueue.take();
    }

    public void release(SlowObject slowObject) {
        // TODO You may want to log a warning if this is false
        slowObjectQueue.offer(slowObject);
    }
}

これもシングルトンにしたいかもしれません。次に、ランナブルで:

public class MyRunnable implements Runnable {

    private SlowObjectPool pool;

    public MyRunnable(SlowObjectPool pool) {
        this.pool = pool;
    }

    @Override
    public void run() {
        // The next line blocks until a SlowObject is available
        SomeObject someObject = null;
        try {
            someObject = pool.take()
            // Do something with someObject
        } catch (InterruptedException ex) {
            // Thread is being ended, allow to end
        } finally {
            if (someObject != null)
                pool.release(someObject);
        }
    }
}

SomeObjectこれにより、オブジェクトが動的に作成されるのではなく、プールが最初に作成されるときにオブジェクトが一度に作成されます。そのため、インスタンスが作成されるのを待つ必要がありません。

于 2012-09-17T19:22:54.870 に答える
3

Java は、 ThreadLocal変数の概念を提供します。このようにRunnable
内で使用できます。

 public class MyJob implements Runnable {
     private static final ThreadLocal < SlowObject > threadLocal = 
       new ThreadLocal < SlowObject > () {
         @Override protected SlowObject initialValue() {
           // construct and return your SlowObject 
         }
       };

     public void run() {
       // work with threadLocal.get()
     }
   }

これにより、Runnable を実行するスレッドごとに、クラス SlowObject のインスタンスが 1 つだけ作成されます。

于 2012-09-17T19:13:55.530 に答える