1

これは、『Java Concurrency in Practice』ブックの BoundedExecutor クラスの実装です。

public class BoundedExecutor {
    private final Executor exec;
    private final Semaphore semaphore;

    public BoundedExecutor(Executor exec, int bound) {
        this.exec = exec;
        this.semaphore = new Semaphore(bound);
    }

    public void submitTask(final Runnable command) throws InterruptedException {
        semaphore.acquire();

        try {
            exec.execute(new Runnable() {
                public void run() {
                    try {
                        command.run();
                    } finally {
                        semaphore.release();
                    }
                }
            });
        } catch (RejectedExecutionException e) {
            semaphore.release();
        }
    }
}

RejectedExecutionException がさらに伝播するのではなく、キャッチされている理由はありますか? この場合、タスクが拒否された場合、タスクを提出した人は賢明ではありません。

catch-block を finally-block に置き換えたほうがよいのではないでしょうか?

これは、Runnable の代わりに Callable を受け入れる BoundedExecutor の私の実装です。

public class BoundedExecutor {
    private final ExecutorService exec; 
    private final Semaphore semaphore; 

    public BoundedExecutor(ExecutorService exec, int bound) { 
        this.exec = exec; 
        this.semaphore = new Semaphore(bound); 
    } 

    public <V> Future<V> submitTask(final Callable<V> command) throws InterruptedException { 
        semaphore.acquire(); 

        try { 
            return exec.submit(new Callable<V>() {
                @Override public V call() throws Exception { 
                    try { 
                        return command.call();
                    } finally { 
                        semaphore.release(); 
                    } 
                } 
            });
        } catch (RejectedExecutionException e) { 
            semaphore.release();
            throw e;
        }
    }
}

それは正しい実装ですか?

ありがとう!

4

2 に答える 2

0

あなたの解決策は間違っていると思います。この呼び出しexec.submit(Callable task)は、クライアントに Future への参照を提供します。この Future での get() の呼び出しは、ユーザーに目的の結果または例外 (CancellationException、ExecutionException など) を提供します。

したがって、exec.submit を try catch ブロックでラップしても役に立ちません。また、execute 呼び出しを try catch ブロックでラップする元の実装が正しいものです。

または、ユーザーのコマンドを callable ではなく future タスクにラップし、FutureTask で done メソッドをオーバーライドして semaphore.release() を呼び出すこともできます。

于 2012-02-21T09:10:15.953 に答える
0

catch を finally に変更する際に発生する問題の 1 つは、タスクがサブミットされ、RejectedExecutionException がスローされない場合に、セマフォを 1 回ではなく 2 回解放することになることです。catch ブロック バージョンで例外を伝播する場合はthrow e;、セマフォを解放した後に追加するだけです。

于 2012-02-21T09:12:26.427 に答える