ExecutorService.submit() не возвращается после отправки задачи

Я хочу сделать асинхронный вызов функции и вернуться, не дожидаясь результата (в Java). Код, который я написал для того же:

ExecutorService executorService = Executors.newSingleThreadExecutor();
executorService.submit(new Callable<Void>() 
{
    public Void call() throws Exception, TimeoutException {
        hostNetworkSystem.updatePortGroup("Management Network", spec);
        return null;
    }
});

Я пробовал и Runnable, и Callable, но когда я отлаживаю код в Eclipse, поток застревает в функции call(), которая не возвращается сразу после отправки задачи.

Я что-то здесь упускаю?

Это застревает в:

    hostNetworkSystem.updatePortGroup("Management Network", spec);

точнее. Действие выполняется, как я вижу результаты, но оно не возвращается отсюда.

Для лучшего понимания вот как выглядит весь вызов:

    public void main()
    {
        try {
            AsyncCall asyncCalls = new AsyncCall();
            List<PortGroupData> portData = asyncCalls.updatePortGroupFuture(hostNetworkSystem, portGroupName,
                portGroupData, modelType, oobmStatus, vlanID);
            return portData;
        } catch (InterruptedException e) {
            e.printStackTrace();
            System.out.println("InterruptedException " + e.getMessage().toString());
        } catch (ExecutionException e) {
            System.out.println("ExecutionException " + e.getMessage().toString());
            e.printStackTrace();
        } catch (Exception e) {
            System.out.println("Exception " + e.getMessage().toString());
            e.printStackTrace();
        }
    }


    public void updatePortGroupFuture(final HostNetworkSystem hostNetworkSystem,
        final String portGroupName, final NetworkParameters networkData, final String modelType,
        final boolean oobmStatus, int vlanID) throws InterruptedException, ExecutionException, Exception

    {
           <some other actions>
           ExecutorService executorService = Executors.newSingleThreadExecutor();            
           executorService.submit(new Callable<Void>() 
           {
              public Void call() throws Exception, TimeoutException {
              hostNetworkSystem.updatePortGroup("Management Network", spec);
              return null;
           }
          });
          return;
    }

3 ответа

Измените свой код как

Future<Void> future = executorService.submit(new Callable<Void>() 
{
    public Void call() throws Exception, TimeoutException {
        System.out.println("before call");
        hostNetworkSystem.updatePortGroup("Management Network", spec);
        System.out.println("after call");
        return null;
    }
});
      try{
                result = future.get(5000, TimeUnit.MILLISECONDS);
            }catch(TimeoutException e){
                System.out.println("Time out after 5 seconds");
                futureResult.cancel(true);
            }catch(InterruptedException ie){
                System.out.println("Error: Interrupted");
            }catch(ExecutionException ee){
                System.out.println("Error: Execution interrupted");
            }
  1. Если вы получаете TimeoutExceptionизмените значение времени ожидания на какое-то большое число. Проверьте до и после выписки. Если вы получили до вызова и не получили после вызова, это означает, что произошло какое-то исключение.

  2. Чтобы узнать исключение, измените submit() в execute() и поймать исключение.

submit() глотает исключения. Посмотрите на этот код

**Inside FutureTask$Sync**

void innerRun() {
        if (!compareAndSetState(READY, RUNNING))
            return;

      runner = Thread.currentThread();
        if (getState() == RUNNING) { // recheck after setting thread
            V result;
           try {
                result = callable.call();
            } catch (Throwable ex) {
               setException(ex);
                return;
            }
           set(result);
        } else {
            releaseShared(0); // cancel
        }
   }


   protected void setException(Throwable t) {
       sync.innerSetException(t);
   }

Посмотрите на этот пост SE и этот вопрос SE:

Выберите между отправкой ExecutorService и выполнением ExecutorService

Попробуйте поставить sysout после submit(...) и посмотрите, будет ли это напечатано. Это означает, что родительский / основной поток не заблокирован в методе call() и возвращен сразу после отправки задачи.

Вы можете захватить Future, возвращенный методом submit, и добавить следующий код после вызова метода submit:

        try {
            future.get();
        }catch(ExecutionException ee){
            System.out.println("exception >>" + ee.getMessage());
        }
        service.shutdown();

Поскольку future.get является блокирующим вызовом, поток, отправляющий задачу, будет ожидать завершения асинхронной операции. Вы также узнаете, есть ли какие-то исключения.

FutureTask хранит исключение в переменной, которая затем будет заключена в ExecutionException и выброшена при вызове метода get. Таким образом, мы можем получить основное исключение, даже когда мы вызываем метод get() для FutureTask

Другие вопросы по тегам