Android останавливает службу после завершения ThreadPoolExcutor

У меня Service запускается независимо с активностью с использованием startService(). Эта служба обрабатывает множество запросов из активности и создает Callable, а затем добавляет в ThreadPoolExecutor. Выглядит это так:

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

Проблема в том, что я хочу, чтобы эта служба работала независимо и параллельно с деятельностью. Таким образом, деятельность не может контролировать, когда ее остановить. Он должен останавливаться только после завершения всех задач.
Я знаю, что есть способ дождаться завершения ThreadPool, но у меня это не сработает, потому что мне не нужно хранить запросы списка. Когда эта служба получает запрос от активности, она должна создать новую задачу и немедленно отправить ее в onStartCommand.
Есть ли способ решить эту проблему?


person R4j    schedule 27.12.2013    source источник


Ответы (1)


Вы проверяли IntentService, это вроде того, что это за тип службы делает. Если вам нужно несколько потоков, вы можете обернуть задачи, которые вы отправляете, проверкой очереди, используемой ThreadPool, чтобы убедиться, что она пуста, и если да, выключите службу и пул потоков.

Callable - это просто интерфейс, поэтому просто сделайте обратный вызов из него.

@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);
       }
    }
};
person Greg Giacovelli    schedule 27.12.2013
comment
Так что мне нужно добавить свой запрос в очередь и проверить, что он пуст? Но как? Нужно ли мне создавать еще один поток с циклом, чтобы проверить, пуст ли он или нет? Я не использую IntentService, потому что он обрабатывает только один запрос за раз, и я хочу управлять своим пулом потоков задач - person R4j; 27.12.2013
comment
@ R4j Вы можете просто обернуть реальную задачу проверкой очереди и, если она пуста, просто stopTheService. Возможно, также стоит использовать обработчик для отправки чека задержки примерно на 300 мс позже. - person Greg Giacovelli; 28.12.2013
comment
Спасибо. Во-первых, CompletionService не имеет getQueue метода. Я думаю, вы имеете в виду ThreadPoolExecutor, который реализует ExecutorService . Во-вторых, когда отправляется последняя задача, будет ли очередь пуста? (конечно, я могу использовать время задержки, но моя задача запроса может быть больше, чем это). Итак, мне просто интересно, действительна ли эта проверка, пока выполняется последняя задача? - person R4j; 28.12.2013
comment
Да, я имею в виду ExecutorService. Это недопустимо во время выполнения, если это не однопоточный исполнитель, поскольку задачи будут в том же потоке, что и проверка. В любом случае вы можете откладывать после каждой задачи, чтобы проверить очередь в основном потоке, а затем вызвать завершение работы через обработчик. - person Greg Giacovelli; 28.12.2013
comment
Спасибо большое, мне это очень помогло :) - person R4j; 28.12.2013