Java – How do I implement a method that returns the result to the event dispatching thread?

How do I implement a method that returns the result to the event dispatching thread?… here is a solution to the problem.

How do I implement a method that returns the result to the event dispatching thread?

I have the following method:

public Object someMethod(Object param) {
    return performLongCalculations();
}

Some time-consuming calculations I put in a separate method :

private Object performLongCalculations() {
    ...
}

The problem is that it returns some calculations. These calculations are performed in the EDT and cause the UI to get stuck.

I tried to solve it in the following way:

public Object someMethod(final Object param) {
    Object resultObject = new Object();
    ExecutorService executorService = Executors.newFixedThreadPool(1);
    Future<Object> future = executorService.submit(new Callable<Object>() {
        @Override
        public Object call() {
            return performLongCalculations(param);
        }
    });
    
executorService.shutdown();

try {
        resultObject = future.get();
    } catch (InterruptedException | ExecutionException  e) {
      // ...
    }
    return resultObject;
}

But the thread is calling future.get(); is blocked until the calculation is complete. I think it works in EDT as well.

Next I tried using SwingWorker :

public Object someMethod(final Object param) {
    SwingWorker<Object, Void> worker = new SwingWorker<Object, Void>() {
        @Override
        protected Object doInBackground() {
            return performLongCalculations(param);
        }

@Override
        protected void done() {
            try {
                get();
            } catch (InterruptedException e) {

}
            catch (ExecutionException e) {

}
        }
    };
    worker.execute();
     what should I return here?
}

Here I need to return the result, but it returns before the thread running in parallel with EDT ends.

Solution

Your question is essentially this:

How can I return a value directly into my Swing GUI from a method where the solution is obtained from long-running code called within a background thread?

In short, the answer is: you don’t need to.

Attempting to do this in any way, shape, or way will mean forcing a background thread to block the GUI event thread until the background thread completes its task, and if that task takes any considerable time, then this will always cause the GUI to get stuck. Instead, you must fetch the information when the background thread completes, rather than getting the result from the method itself. This is usually done using some sort of callback mechanism.

For example, in this code:

public void someMethod(final Object param) {
    SwingWorker<Object, Void> worker = new SwingWorker<Object, Void>() {
        @Override
        protected Object doInBackground() {
            return performLongCalculations(param);
        }

@Override
        protected void done() {
            try {
                Object something = get();
                
 (A)
                
} catch (InterruptedException e) {
                 do handle these exceptions!
            }
            catch (ExecutionException e) {
                 do handle these exceptions!
            }
        }
    };
    worker.execute();
    
 (B)
}

You provide the result to the GUI at location (A) instead of as the return value of the method, location (B).

Alternatively, you can attach a PropertyChangeListener to the SwingWorker, listen for when the worker’s status property changes to SwingWorker.StateValue.DONE, and then call the .get() worker and push the returned value onto the GUI. This is my preferred approach because it generally allows for lower code coupling.

Related Problems and Solutions