【问题标题】:IntentService and ThreadpoolIntentService 和线程池
【发布时间】:2013-12-22 13:12:03
【问题描述】:

我有一个 IntentService,它应该像管理器一样工作,并在提交到 ThreadPool 的队列 (Runnable) 中创建任务。

我对 IntentService 的生命周期有点困惑:

protected abstract void onHandleIntent (Intent intent) 方法已经在一个单独的线程上运行。在onHandleIntent 中,我将创建一个新的 Runnable 实例并将其提交给 ThreadPool。我的服务如下所示:

    public class SyncService extends IntentService {

    private final ThreadPoolExecutor threadPool;

    public SyncService() {
        super("SyncService");
        BlockingQueue<Runnable> queue = new LinkedBlockingQueue<Runnable>();
        threadPool = new ThreadPoolExecutor(1, 1, 20, TimeUnit.SECONDS, queue);
    }

    @Override
    public void onCreate() {
        super.onCreate();
        EventBus.getInstance().register(this);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        EventBus.getInstance().unregister(this);
    }

    @Override
    protected void onHandleIntent(Intent intent) {

        if (intent.getAction().equals("sync")){
            threadPool.submit(new SyncRunnable());
        }else 
            if(intent.getAction().equals("delete")){
            threadPool.submit(new DeleteRunnable());
        } else 
            if(intent.getAction().equals("register")){
            threadPool.submit(new RegisterRunnable())
        }

    }
}

我的问题:

  1. 在 IntentService 中使用 ThreadPool 是个好主意吗?
  2. 如果我使用 ThreadPool,如果 Threadpool 没有更多 Runnables 可以执行或排队,IntentService 将被销毁,对吗?
  3. IntentService 是否已经是我想要实现的目标,我是否应该在 onHandleIntent() 因为这个方法已经在 IntentService 工作线程?如果是,是否有队列限制 意图,因为 onHandleIntent() 可以在 30 秒之前运行 完成并处理下一个 Intent。

【问题讨论】:

    标签: android multithreading threadpool intentservice


    【解决方案1】:

    在 IntentService 中使用 ThreadPool 是个好主意吗?

    不是真的。 IntentService 已经是您尝试实现的单线程(串行)变体。我会直接从Service 派生。

    如果我使用 ThreadPool,如果 Threadpool 没有更多 Runnables 可以执行或排队,IntentService 将被销毁,对吗?

    没有。一旦您从onHandleIntent 返回,IntentService 可以进入销毁状态 - 即立即因为threadPool.submit 是非阻塞的。在 source 中,它使用启动服务时获得的 startId 调用 stopSelf(int)

    private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }
    
        @Override
        public void handleMessage(Message msg) {
            onHandleIntent((Intent)msg.obj);
            stopSelf(msg.arg1);
        }
    }
    

    如果您使用最新(最高)的 startId 调用 stopSelfService 将进入销毁状态。如果队列中有新的开始,它将继续运行。

    如果服务进入销毁状态,它不会杀死你的线程池,因为它不知道它。问题是Android现在认为你的服务已经死了,它不再是保持你的应用程序进程的理由。服务运行 vs 已销毁状态本质上只是一种告诉 Android 发生了一些事情并且您不想被销毁的方式。

    如果您想以正确的方式进行操作,则必须使服务状态与实际发生的情况保持同步。

    IntentService 是否已经是我想要实现的目标,我是否应该在 onHandleIntent() 中简单地执行我的(长时间运行的)可运行代码,因为该方法已经在 IntentService 工作线程上运行?

    如果您对单线程串行执行感到满意,可以。这就是onHandleIntent 为您所做的。

    如果是,intent 是否存在队列限制,因为 onHandleIntent() 在完成和处理下一个 Intent 之前最多可能运行 30 秒。

    没有限制(据我所知,它是一个链表)。但是也没有什么能阻止你产生比它可以处理的更多的任务,这最终会导致某种溢出。

    【讨论】:

    • 谢谢!您已经证实了我的怀疑,即 IntentService 已经是我正在寻找的东西(运行命令的单线程队列)。 IntentService 是一个单例,只有在处理完最后一个等待的 Intent 时才会被销毁,对吗? IntentService 是否可以取消所有等待的 Intent?由于 IntentService 有一个上下文,我可以自己启动吗?如果发生错误,我想在等待一段时间后重试(这应该会随着失败次数成倍增长)。我看到两种可能性:在 onHandleIntent() Thread.sleep() 中使用或使用 AlarmManager。有什么建议吗?
    • 是单例,是的,只有在所有任务完成后才会被销毁(Android 仍然可以杀死你的整个进程),任务以严格的顺序处理,所以最新的一个进入它需要的那个在它被销毁之前完成。 IntentService 没有内置的方法来取消任务,一旦它们被排队,它们就会被处理。如果需要,您需要添加它。
    • 是的 Context 可以用来启动它自己。指数重试应该可以正常工作。如果您谈论最多一秒钟左右的睡眠,我会简单地使用睡眠。如果有任何最好的警报管理器或第三个选项,则更长的时间会阻止其他任务:获取IntentService 的源并使用sendMessageDelayedHandler 来添加延迟启动的方式。
    猜你喜欢
    • 1970-01-01
    • 2011-11-09
    • 1970-01-01
    • 1970-01-01
    • 2011-09-29
    • 1970-01-01
    • 1970-01-01
    • 2023-03-28
    • 2011-10-10
    相关资源
    最近更新 更多