提交任务后ExecutorService.submit()不返回

时间:2015-12-12 03:59:57

标签: java executorservice futuretask

我想对函数进行异步调用并返回而不等待结果(在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中的代码进行调试时,线程在调用时被卡住()函数在提交任务后没有立即返回。

我在这里错过了什么吗?

它陷入了:

    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 个答案:

答案 0 :(得分:1)

将您的代码更改为

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,请将超时值更改为某个较大的数字。 在通话前检查&amp;电话结束后。如果你在通话前得到并且没有接到电话,则意味着发生了一些异常。

  2. 要了解该异常,请将submit()更改为execute()并捕获异常。

  3. submit()吞下例外情况。看看这个code

    **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 Post和这个SE问题:

    Choose between ExecutorService's submit and ExecutorService's execute

答案 1 :(得分:0)

尝试在提交(...)后输入一个sysout,看看是否打印出来。这表示父/主线程未在call()方法中被阻止,并在提交任务后立即返回。

答案 2 :(得分:0)

您可以捕获submit方法返回的Future,并在submit方法调用后添加以下代码:

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

由于future.get是一个阻塞调用,提交任务的线程将等待异步操作完成。你也会知道它是否会抛出任何例外。

FutureTask将异常存储在一个变量中,该变量随后将被包装在ExecutionException中,并在调用get方法时抛出。因此,即使我们在FutureTask上调用get()方法

,我们也可以获得底层异常