1

I want to make an asynchronous call to a function and return without waiting for the result (in Java). The code I have written for the same is:

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

I have tried both Runnable and Callable but when I debug through the code in Eclipse, the thread gets stuck at the call() function doesn't return immediately after submitting the task.

Am I missing something here?

It gets stuck at:

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

to be precise. The action is carried out as I can see the results, but it doesn't return from here.

For better understanding, this is how the entire call looks:

    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;
    }
  • Gets stuck at `call` or `submit`? Do you have breakpoonts set somewhere? Have you tried putting some logging statements inside your callable to see if it's getting called when you run (and not debug) your app? – Krease Dec 12 '15 at 04:08

3 Answers3

1

Change your code as

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. If you get TimeoutException, change the time out value to some big number. Check for before call & after call statements. If you get before call and did not get after call, it implies some exception happened.

  2. To know the exception, change submit() to execute() and catch exception.

submit() swallows exceptions. Have a look at this 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);
   }

Have a look at this SE Post and this SE question:

Choose between ExecutorService's submit and ExecutorService's execute

Community
  • 1
  • 1
Ravindra babu
  • 37,698
  • 11
  • 250
  • 211
0

Try putting a sysout after submit(...) and see if that gets printed. That indicates the parent/main thread is not blocked on the call() method and returned immediately after submitting the task.

0

You can capture the Future returned by the submit method and add the following code after the submit method invocation:

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

Since future.get is a blocking call, the thread submitting the task will wait for the async operation to complete. You will also get to know if its throwing any exceptions.

FutureTask stores the exception in a variable which will then be wrapped in a ExecutionException and thrown when get method is called. So we can get the underlying exception even when we call get() method on FutureTask

akki
  • 423
  • 2
  • 12
  • We are not looking for a blocking operation. We just want to make the call to update and return immediately. Hence I had not used the "get()". – Shuchita Kumar Dec 14 '15 at 15:56