1

I have a Service run independently with activity using startService(). This service handle many requests from activity and create Callable then add into ThreadPoolExecutor. It looks like this:

private ExecutorService requestExecutor;
private CompletionService<Result> requestHandleService;

 @Override
public int onStartCommand(final Intent intent, int flags, int startId) {
    // Create new Request Task and submit
    Callable<Result> request = new Callable<Result>(){
              public Result call() throws Exception {
              }
            };

    requestHandleService.submit(task);
    return super.onStartCommand(intent, flags, startId);
}  


 @Override
public void onDestroy(){
    super.onDestroy();
    Log.d(TAg,"onDestroy service");
    try{
        if(requestExecutor!= null){
            requestExecutor.shutdown();
        }
    }catch(Exception ex){
        Ln.e(ex);
    }finally{
        requestExecutor= null;
        requestHandleService= null;
    }
}

The problem is that I want this Service run independently and parallel with activity. So activity can't control when to stop it. It should only stop when all tasks finished.
I know there is a way to wait for ThreadPool complete, but this can't work for me, because I don't need to keep the list requests. When this service receive request from activity, it should create new a task and submit immediately in onStartCommand.
Is there any way to solve this?

Community
  • 1
  • 1
ductran
  • 10,043
  • 19
  • 82
  • 165

1 Answers1

1

Have you checked out IntentService, this is sort of what this type of service does. If you need the multiple threads then you could wrap the tasks you submit with a check for the Queue used by the ThreadPool to see if it is empty, and if so, shutdown the service and the threadpool.

Callable is just an interface, so just make a callback out of it.

@Override
public void onCreate() {
   mHandler = new Handler();
}

@Override
public int onStartCommand(final Intent intent, int flags, int startId) {
    // Create new Request Task and submit

    Callable<Result> request = new Callable<Result>(){
              public Result call() throws Exception {
                 Result result = // ... mRealTask.call();
                 mHandler.postDelayed(queueCheck, 300);
                 return result;
               }
            };
    requestHandleService.submit(task);
    return super.onStartCommand(intent, flags, startId);
}

Runnable queueCheck = new Runnable() {
    public void run() {
       if (requestExecutor.getQueue().isEmpty()) {
              stopService(new Intent(this, getClass()));
              mHandler.removeCallbacks(this);
       }
    }
};
Greg Giacovelli
  • 10,164
  • 2
  • 47
  • 64
  • So do I have to add my request to queue and check it empty? But how? Do I have to create another thread with loop to check it is empty or not? I don't use `IntentService` because it just handle only one request at time and I want to control my tasks thread pool – ductran Dec 27 '13 at 19:34
  • @R4j You can just wrap around the real task the check for the queue and if it is empty just stopTheService. Might be also worth it to use a handler to post delay a check about 300 ms later too. – Greg Giacovelli Dec 27 '13 at 20:01
  • Thanks. First, the `CompletionService` don't have `getQueue` method. I think you mean `ThreadPoolExecutor` which implements `ExecutorService `. Second, when the last task is submitted, is the queue empty? (of course I can use delay time, but my request task can be longer than it). So, I just wonder if this check is valid while the last task is running? – ductran Dec 28 '13 at 11:31
  • Yep I do mean the `ExecutorService`. It's not valid during the running unless it is a single threaded executor since the tasks would be on the same thread as the check. Anyways, you could delay after each task to check the queue on the main thread and then call shut down via a handler. – Greg Giacovelli Dec 28 '13 at 17:15