Практический параллелизм Java: реализация BoundedExecutor - PullRequest
1 голос
/ 21 февраля 2012

Это реализация класса BoundedExecutor в книге Java Concurrency in Practice:

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 на блок finally?

Это моя реализация BoundedExecutor, который принимает Callable вместо Runnable:

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

Это правильная реализация?

Спасибо!

Ответы [ 2 ]

0 голосов
/ 21 февраля 2012

Одна проблема, которую я вижу с изменением перехвата на finally, заключается в том, что в случае, если задача действительно отправлена, а RejectedExecutionException не генерируется, вы в конечном итоге освободите семафор дважды, а не один раз. Если вы хотите распространить исключение в версии блока catch, вы можете просто добавить throw e; после освобождения семафора.

0 голосов
/ 21 февраля 2012

Я думаю, ваше решение неверно.Вызов exec.submit(Callable task) дает клиенту ссылку на Future, вызов get () для этого Future дает пользователю либо желаемый результат, либо исключение (CancellationException, ExecutionException и т. Д.).

Итак, переносexec.submit в блоке try catch не поможет, и первоначальная реализация переноса вызова execute в блок try catch является правильной.

В качестве альтернативы вы можете заключить команду пользователя в будущую задачу, а невызываемый и в вашей FutureTask переопределяет метод done для вызова semaphore.release ().

...