2013-07-03 2 views
1

У меня есть какая-то периодическая операция, которая должна быть выполнена в моем приложении, например, период T. На данный момент я использую Timer.scheduleAtFixedRate(TimerTask, 0, T). Теперь я хочу избежать перекрытия отдельных операций (в некоторых случаях одна операция может занять больше времени, чем T). Я прочитал Timer Реализация использует один поток для выполнения операций, поэтому в стандартных ситуациях не будет перекрываться. Проблема в том, что в моем случае одиночные операции не выполняются непосредственно TimerTask, переданным в Timer: операции начинаются только с него, и они выполняются асинхронно.Java - Как избежать периодического выполнения операции перекрытия

Таким образом, при выполнении TimerTask может начаться новая операция до завершения предыдущего. Вместо этого, если происходит перекрытие, я хочу дождаться окончания предыдущего выполнения и начать новую операцию, как только будет завершена предыдущая.

Какая была бы лучшая реализация для получения этого поведения? Должен ли я переключиться с Таймера на другую поддержку? Это Android-среда, поэтому я предпочитаю Java-стандарт (util.concurrent) или некоторые версии на базе Android вместо других на основе Spring Quartz и других конкретных фреймворков.

+0

Почему вы не планируете следующую задачу в конце текущего? Это решит все ваши проблемы и позволит избежать разряда батареи, если продолжительность вашей задачи немного меньше, чем T –

+0

Это может быть решение, но таким образом мне нужно явно контролировать период выполнения, помня о отметке времени начала, проверяя сколько времени занимает выполнение и т. д. Разве нет более элегантного решения? PS: Можете ли вы лучше объяснить, как это конкретное решение будет экономить батарею, если продолжительность задачи немного меньше, чем T? – user1781028

+0

Вы говорите мне, что ваша задача занимает иногда больше, чем T секунд, потому что вы боитесь перекрыться. Это означает, что если ваша задача равна T минус 1 секунда, ваша задача будет запускаться каждый T с длительностью T-1 и означает, что у вас есть только 1 секунда, когда ваша батарея не используется. Планирование второй задачи после T секунд после окончания первого даст вам T-секундные разряды, не разряжая батарею. Или, может быть, я что-то не понял? –

ответ

0

Для этого вы можете использовать Executors.newScheduledThreadPool(1). Это намного проще в использовании, чем Timer{,Task}.

+0

И что будет гарантировать, что отдельные операции не будут перекрываться? Даже создание однопоточного пула, поскольку я писал отдельные операции, является асинхронным и напрямую не выполняется потоком. – user1781028

+0

Ну, это то, что выполняет «ExecutorService»: он выполняет задачи асинхронно; и поскольку у вас есть только один поток, пока предыдущая задача не будет завершена, вторая не будет выполнена. – fge

+0

Даже Timer и TimerTask выполняются асинхронно, поскольку они выполняются в отдельном потоке. Я написал другое мнение. В моем случае одиночные операции являются асинхронными, поэтому поток не занят при выполнении операции. Он выполняется только для запуска операции, которая завершается в фоновом режиме. Таким образом, многократное выполнение потока начнет параллельные выполнение операции, и я хочу избежать этого. – user1781028

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