В настоящее время я работаю над реализацией Service
, который по запросу будет выполнять некоторые работы над несколькими параллельными потоками.Реализация пула потоков внутри службы
Моя реализация основана на классе ThreadPoolExecutor
наряду с LinkedBlockingQueue
.
Как правило, после завершения всех задач и отсутствия ожидающих задач в очереди, я хотел бы остановить службу (хотя позже служба может быть запущена снова и следовать той же логике).
Мне удалось достичь желаемого результата, используя приведенный ниже код, но я не уверен, правильно ли этот подход.
public class TestService extends Service {
// Sets the initial threadpool size to 3
private static final int CORE_POOL_SIZE = 3;
// Sets the maximum threadpool size to 3
private static final int MAXIMUM_POOL_SIZE = 3;
// Sets the amount of time an idle thread will wait for a task before terminating
private static final int KEEP_ALIVE_TIME = 1;
// Sets the Time Unit to seconds
private static final TimeUnit KEEP_ALIVE_TIME_UNIT = TimeUnit.SECONDS;
// A queue of Runnables for the uploading pool
private final LinkedBlockingQueue<Runnable> uploadQueue = new LinkedBlockingQueue<Runnable>();
// A managed pool of background upload threads
private final ThreadPoolExecutor uploadThreadPool = new ThreadPoolExecutor(
CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_TIME, KEEP_ALIVE_TIME_UNIT,
uploadQueue) {
@Override
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
if (getActiveCount() == 1 && getQueue().size() == 0) {
// we're the last Runnable around + queue is empty, service can be
// safely stopped.
TestService.this.stopSelf();
}
}
};
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// execute a new Runnable
uploadThreadPool.execute(new TestRunnable());
/**
* Indicating that if Android has to kill off this service (i.e. low memory),
* it should not restart it once conditions improve.
*/
return START_NOT_STICKY;
}
@Override
public void onDestroy() {
uploadThreadPool.shutdownNow();
uploadQueue.clear();
super.onDestroy();
}
}
У меня есть кое-что, о чем я еще не уверен.
Предполагая, что
onDestroy
называли, это с уверенностью предположить, что моя реализация будет прерывать все запущенные потоки и безопасно очистить незавершенные задачи, не прерывая каким-то образом с внедрением вThreadPoolExecutor
класса? причина, по которой я спрашиваю, связана с тем, что очередь связана с исполнителем, и, возможно,shutdownNow
является асинхронным и зависит от состояния очереди. Есть ли лучший способ сделать это?Я правильно использую эту логику внутри
onDestroy
? из моего опыта есть некоторые случаи, когда служба убита (т. е. низкая память), и этот обратный вызов не вызывается. Должен ли я выполнять аналогичный подход и в других местах?Было бы лучше объявить мою очередь & членами-исполнителями как статическими?- Как указано @TheTwo"Excecutor cannot be re-used once shutdown is called"
.ThreadPoolExecutor
класс ожидаетBlockingQueue
, каковы плюсы/минусы использования других типовBlockingQueue
реализаций (т.е.ArrayBlockingQueue
)?Относительно того, как я обнаруживаю, когда очередь пуста & больше нет ожидающих задач (в частности, внутри обратного вызова
afterExecute
). Это лучший способ сделать это? Или я могу получить указание, что очередь пуста, а задачи закончены по-другому?
Цените любую помощь!
re # 5, следуя http://www.youtube.com/watch?v=xHXn3Kg2IQE У меня сложилось впечатление, что, как только служба завершила свою работу, ее следует остановить, сохранить аккумулятор и сообщить системе, что он может высвободить ресурсы и что служба больше не используется. Разве андроид не принимает решения об уничтожении определенных запущенных компонентов на основе такой информации? – cdroid
Если вы планируете никогда больше не пользоваться услугой, рекомендуется очистить ее. Но представьте себе следующее: 'for (int i = 0; i
TwoThe