2014-11-26 2 views
0

Я пытаюсь понять приведенную ниже примерную реализацию интерфейса java.util.concurrent.Executor, представленную в его API.Интерфейс Java Executor Пример реализации из «API-интерфейса Executor»

class SerialExecutor implements Executor { 
    final Queue<Runnable> tasks = new ArrayDeque<Runnable>(); 
    final Executor executor; 
    Runnable active; 

    SerialExecutor(Executor executor) { 
    this.executor = executor; 
    } 

    public synchronized void execute(final Runnable r) { 
    tasks.offer(new Runnable() { 
     public void run() { 
     try { 
      r.run(); 
     } finally { 
      scheduleNext(); 
     } 
    } 
    }); 
    if (active == null) { 
     scheduleNext(); 
    } 
    } 

    protected synchronized void scheduleNext() { 
    if ((active = tasks.poll()) != null) { 
     executor.execute(active); 
    } 
    } 
} 

Здесь проходил Runnable экземпляр заворачивают в другой Runnable экземпляр и хранится в очереди задач, а затем scheduleNext() вызывается. Является ли переданный экземпляр Runnable скопированным (защищенным) экземпляром другого Runnable? Если нет, то зачем это делать, кроме как выполнить следующие Runnables из очереди?

Просьба уточнить мои сомнения.

ответ

0

Вы хотите, чтобы scheduleNext() вторая задача только после того, как первый закончен.

Обертывание оригинала Runnable в другое, которое его вызывает, и после этого звонки scheduleNext() - удобный и надежный способ сделать это.

Таким образом, вы можете обойтись только одним потоком для «эффективного использования» и «управления очередью».

Альтернативой будет отдельный фоновый поток, который контролирует текущую задачу (например, через join()), а затем планирует новый.

Является ли переданный экземпляр Runnable копией (защитой) в другой экземпляр Runnable?

Не совсем. Конечно, скопирован указатель на Runnable, но он все же указывает на тот же Runnable. Это не «защитный», поскольку состояние Runnable теоретически может быть обновлено, пока оно поставлено в очередь.

Если нет, то зачем это использовать, за исключением выполнения следующих Runnables из очереди?

Почему это недостаточно? В конце концов, это нужно сделать.

+0

Я не понимаю вашего намерения «продуктивного использования» и «управления очередью». –

+0

Ну, управление очередью не является «продуктивным» для вашего приложения. Это накладные расходы. В идеале вы хотите тратить ресурсы только на код внутри вашего Runnable. – Thilo

+0

Спасибо за вашу ясность. Теперь я понял. Есть ли какие-либо проблемы, если я просто добавляю переданный Runnable в очередь, вместо того, чтобы переносить его в другой Runnable. –

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