Trota
Trota

Reputation: 145

ExecutorService, how to know when all threads finished without blocking the main thread?

I have a multithreaded implementation where i create an ExecutorService and submit tasks to be executed, i want to know when all the threads is submited have finished without blocking the main thread and the UI. I've tried ExecutorService.awaitTermination() but it blocks the main thread and the UI. I've searched alot but i can't seem to find an elegant way of doing this. I'm currently thinking about creating another thread that counts the amount of threads finished and launches an event when they all finished, but that doesn't to be a good approach and i wanted a better solution!

Upvotes: 7

Views: 7931

Answers (5)

Dev
Dev

Reputation: 12206

Use a SwingWorker to shutdown the thread pool and call awaitTermination(). This will prevent the UI from blocking and call done() from the Event Dispatch Thread on your SwingWorker implementation which you can use to trigger the whatever UI changes you need.

If you desire to keep track of the threads running via a UI update you can use the the worker thread to monitor this in a loop and call publish() with arguments which then get passed to your implementation of process() on the EDT.

Upvotes: 7

Anuj Kulkarni
Anuj Kulkarni

Reputation: 2199

Using CountDownLatch

 

CountDownLatch latch = new CountDownLatch(totalNumberOfTasks);
ExecutorService taskExecutor = Executors.newFixedThreadPool(4);
while(...) {
  taskExecutor.execute(new MyTask());
}

try {
  latch.await();
} catch (InterruptedException E) {
   // handle
}

and within your task (enclose in try / finally)

 latch.countDown();

Or on ExecutorService you call shutdown() and then awaitTermination()

 
ExecutorService taskExecutor = Executors.newFixedThreadPool(4);
while(...) {
  taskExecutor.execute(new MyTask());
}
taskExecutor.shutdown();
try {
  taskExecutor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
} catch (InterruptedException e) {
  ...
}

Also have a look at THIS answer

Upvotes: 2

shams
shams

Reputation: 3518

You can maintain a separate thread to track when the executor service instance shuts down:

    final ExecutorService execSvc = ...;
    execSvc.submit(task1);
    ...
    execSvc.submit(taskN);
    // important to request the exec service to shut down :)
    execSvc.shutdown();

    new Thread(new Runnable() {

        public void run() {
            while (!execSvc.isTerminated()) {
                try {
                    execSvc.awaitTermination(60, TimeUnit.SECONDS);
                } catch (InterruptedException e) {
                    // ignore exception
                }
            }
            System.out.println("ExecSvc.run: exec service has terminated!");
            // possibly submit a task using SwingUtilities.invokeLater() to update the UI
        }

    }).start();

Upvotes: 2

Hovercraft Full Of Eels
Hovercraft Full Of Eels

Reputation: 285440

Why not use a CountDownLatch and then notify the main thread when the latch has been completed.

Upvotes: 4

ratchet freak
ratchet freak

Reputation: 48226

isTerminated() will do

note however that both awaitTermination and isTerminated will only give you a meaningful result after you have called shutdown

Upvotes: 2

Related Questions