在服务中实现一个线程池

我目前正在努力实现一个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 (ie low memory), * it should not restart it once conditions improve. */ return START_NOT_STICKY; } @Override public void onDestroy() { uploadThreadPool.shutdownNow(); uploadQueue.clear(); super.onDestroy(); } } 

所以我有一些事情我还不确定。

  1. 假设onDestroy被调用,是否安全地假设我的实现将中断所有正在运行的线程,并将安全地清除挂起的任务,而不会中断与ThreadPoolExecutor类的实现? 我所要求的原因是因为队列与执行程序相关联,也许shutdownNow是asynchronous的并取决于队列的状态。 有没有更好的方法来做到这一点?

  2. 我正确的执行这个逻辑内onDestroy ? 根据我的经验,有些情况下服务被杀死(即低内存),并且这个callback没有被调用。 我应该在其他地方也采取类似的做法吗?

  3. 将我的队列和执行器类成员声明为静态会更好吗? – 正如@TheTwo所述"Excecutor cannot be re-used once shutdown is called"

  4. ThreadPoolExecutor类期望BlockingQueue ,使用其他types的BlockingQueue实现(即ArrayBlockingQueue )的优点/缺点是什么?

  5. 关于我目前检测队列为空的方式,没有更多的待处理的任务(特别是在afterExecutecallback中) – 这是做这件事的最好方法吗? 或者我可以得到一个队列是空的指示,并以另一种方式完成任务?

感谢任何帮助!

Solutions Collecting From Web of "在服务中实现一个线程池"

我认为你正在试图实施一项服务,这引入了许多问题,但没有解决。 实际上,你可以通过一行代码来减less调用代码 – 执行程序的创build,但是不能去精细控制代码。 调度许多任务没有任何好处,因为这已经被OS的线程调度器解决了。 另外一个恶意的调用者可以通过添加足够的while(true) sleep(100);来打破其他几个程序while(true) sleep(100); 循环。

在你的问题上:

  1. 你不能确保所有的线程都被正确的中断,因为没有办法中断一个没有正确看中断标志的线程。 while(true) ;System.exit()外不能中断。 理论上你可以停止一个线程,但这个function由于某种原因而被弃用,因为它可能会使实际任务处于未完成/未完成状态(iE离开TCP连接半开)。

  2. 不,你没有正确的执行。 因为一旦任务离开,队列就会消失在空白区域,然后一旦调用shutdown,就不能重新使用一个Excecutor。 所以你至less需要在服务启动时创build一个新的Excecutor实例,你真的应该弄清楚如何处理剩下的任务。

  3. 不,因为2。

  4. 列表types的优缺点取决于你的用例。 ArrayList在成长/收缩时成本较高,但在索引特定元素(indexOf)时成本较低,而链接列表则相反。 由于您的队列总是添加到尾部,不关心任何其他元素,而是第一个,它是经常增长/收缩,链表是最好的select。

  5. 你不应该以这种方式停止任务,因为线程的执行顺序是不确定的。 在最坏的情况下,你的调用程序每次都会被中断,直到服务执行完毕,这将导致服务不经意的开始和停止,而浪费了大量的处理时间。 为什么你甚至想停止服务? 如果没有什么可做的,除了使用几个字节的内存之外,它什么都不会做。

几年前,我写了这篇关于pipe理服务中的线程的文章 。 你可以使用这个软件本身,或者只是想自己做一些想法。

  1. 不,shutdownNow尝试中断当前正在执行的任务。 没有保证,它将能够做到这一点
  2. 是的。 从文档:

一旦这两种情况都不存在,就会调用服务的onDestroy()方法,服务被有效终止。 所有清理(停止线程,取消注册接收器)应该从onDestroy()返回完成。

  • 没有理由让这些成员声明为静态的。 static成员与类相关联,而不是与任何对象关联,而常见的用法是在不同的(服务在你的情况下)实例之间共享相同的静态成员。
  • 您应该仔细阅读有关BlockingQueue<E>接口的所有可能实现的文档,但是我怀疑,对于正常情况下的使用,您将看到与性能angular度的差异。