2013-12-10 2 views
0

Мне нужно периодически выполнять некоторые данные, для чего я хочу создать задачу, которая запрашивает некоторые данные с разных серверов. Некоторым серверам потребуется больше времени для обработки запроса и возврата ответа, чем другие.Расписание нескольких задач на несколько потоков

Вот почему я хочу создать задачу для каждого сервера и выполнить задачи async. Если я использую ScheduledExecutorService следующим образом, каждая задача будет выполняться в своем потоке или все задачи будут выполняться в том же потоке?

Что произойдет, если задача выбрасывает исключение, все остальные запланированные задачи потерпят неудачу?

this.scheduler = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() { 
       @Override 
       public Thread newThread(Runnable r) { 
        return new Thread(r, "collectionThread"); 
       } 
      }); 

for (String url:urls){ 
    this.scheduler.scheduleWithFixedDelay(new CollectorTask(url), 
                startupDelaySeconds, 
                scheduleRateSeconds, 
                TimeUnit.SECONDS); 
} 

ответ

2

Вы используете однопоточную службу-исполнитель, поэтому все задачи выполняются последовательно. Если какое-либо из них выдает исключение, все последующие исполнения выполняются.

Вы можете использовать

Executors.newScheduledThreadPool(4) // 4 is the max number of parallel jobs 

... чтобы параллельное выполнение и обернуть тело переданной работы в

try { 
    ... 
} catch(Exception e){ 
    logger.warn("exception during task execution", e); 
} 

для регистрации ошибок без распространяющихся их.

Возможны незначительные задержки (несколько миллисекунд) и зависят от ОС, задачи никогда не будут выполняться раньше запланированного времени. Выполнение задачи может быть отложено из-за предыдущих длительных прогонов или отсутствия свободных потоков, но следующие исполнения будут выполняться исходным расписанием: initialDelay + n * period.

+0

Есть ли способ выполнить задачи async и предотвратить отмену задач после того, как один из них не работает? – Marius

+0

Да, я обновил ответ. –

+0

'Если какой-либо из них выдает исключение, все последующие исполнения выполняются.« Я так не думаю, текущий поток исполнителей будет завершен, но новый будет создан исполнителем. – Katona

0

Да, что вы делаете, это создание двух исполнителей потоков. Первый - это запланированный исполнитель, который выполняет runnable, который предназначен для запуска вашего фактического runnable. Все это приводит к тому, что он создает экземпляр вашей задачи и передает ее реальному исполнителю. Этот исполнитель должен просто быть обычным пулом потоков, который будет обрабатывать задачи.

private final ScheduledExecutorService scheduledExecutor = Executors 
      .newSingleThreadScheduledExecutor(); 
private final ExecutorService executor = Executors.newCachedThreadPool(); 

    private class SubmitTaskRunnable implements Runnable { 

     @Override 
     public void run() { 
      executor.execute(new TaskRunnable()); 
     } 

    } 

Запланируйте SubmitTaskRunnable на своем запланированном исполнителе, потому что он не будет выбрасывать какие-либо исключения. Пусть ваша фактическая задача выполняется внутри кэшированного исполнителя, позволяя одновременно запускать несколько задач, даже если предыдущие еще не закончены.

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