2012-02-21 2 views
1

Это реализация класса BoundedExecutor в Java Параллелизм в практике книге:Java Параллелизм на практике: реализация 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 быть пойманным вместо того, чтобы позволить ему распространяться дальше? В этом случае, если задача отвергнута, любой, кто отправляет задание, не будет более мудрее.

Не лучше ли заменить блок блокировки блоком finally?

Это моя реализация 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; 
     } 
    } 
} 

ли это правильное применение?

Спасибо!

ответ

0

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

+0

Правильно! Я скорректировал мою версию BoundedExecutor выше. Работает ли он правильно? –

0

Возможно, ваше решение неверно. Вызов exec.submit(Callable task) дает клиенту ссылку на Будущее, вызов get() в этом Будущем дает пользователю либо желаемый результат, либо исключение (CancellationException, ExecutionException et-all).

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

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

+0

Я знаю, что такое «Будущее». Не могли бы вы рассказать о том, почему мой BoundedExecutor не работает? –

+0

Ну, были причины, о которых я думал; Кажется, не вспоминают все. 1) вы возвращаете будущее, скажем, пользователь отменяет будущее, этот исполнитель, похоже, не справляется с этим. Кажется, я ничего не могу вспомнить сейчас, но я обновляю свой ответ, предлагая альтернативное решение. – Scorpion

+0

Семафор выпущен в последнем блоке, когда я вызываю 'cancel (true)' в моем Будущем для прерываемой задачи. –

Смежные вопросы