IntentService and Threadpool

android, intentservice, multithreading, threadpool

Solution

Is it a good idea to use a ThreadPool in a IntentService?

Not really. IntentService is already a single threaded (serial) variant of what you try to achieve. I would derive directly from `Service`.

If I use a ThreadPool, than the IntentService will be destroyed if the Threadpool has no more Runnables to execute or queued, right?

No. IntentService can go into the destroyed state once you return from `onHandleIntent` - i.e. immediately because `threadPool.submit` is non-blocking. Within the source it calls `stopSelf(int)` with the startId it got when the service was started.

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);
    }
}

A `Service` will go into destroyed state if you call `stopSelf` with the latest (highest) startId. It will keep running if a newer start is in the queue.

If the service goes into destroyed state it will not kill your thread pool because it has no knowledge about it. The problem is that Android now thinks that your service is dead and it will no longer count as a reason to keep your app process. The service running vs destroyed state is essentially just a way to tell Android that there is something going on and you don't want to get destroyed.

If you want to do it the right way you have to keep the service state in sync with what is actually going on.

Is IntentService already something that I want to achieve and should I simply execute my (long running) Runnable code in the onHandleIntent() because this method alread runs on the IntentService worker Thread?

If you are happy with single threaded serial execution yes. That's what `onHandleIntent` does for you.

If yes, is there a queue limit for intent, since onHandleIntent() could run up to 30 seconds before finishing and handling the next Intent.

There is no limit (it's a linked list as far as I can tell). But there is also nothing that stops you from producing more tasks than it can handle which will ultimately lead to some kind of overflow.

Problem

i have an IntentService that should act like a manager and create Tasks in a queue (Runnable) that are submitted to a ThreadPool. Im a little bit confused of the lifecycle of an IntentService: The method `protected abstract void onHandleIntent (Intent intent)` runs already on a separated Thread. In the `onHandleIntent` I would create a new Runnable instance and submit it to the ThreadPool. My Service looks like this: ``` 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()) } } } ``` My questions: - Is it a good idea to use a ThreadPool in a IntentService? - If I use a ThreadPool, than the IntentService will be destroyed if the Threadpool has no more Runnables to execute or queued, right? - Is IntentService already something that I want to achieve and should I simply execute my (long running) Runnable code in the `onHandleIntent()` because this method alread runs on the IntentService worker Thread? If yes, is there a queue limit for intent, since onHandleIntent() could run up to 30 seconds before finishing and handling the next Intent.

Original source