我正在努力实现一个 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
回调) - 这是最好的方法吗?或者我可以得到队列为空并且任务以其他方式完成的指示吗?
感谢任何帮助!