Wait for thread java

Waiting threads to finish completely in Java

In this article, we will learn how to wait our threads to finish completely. Let’s get started.

Table of contents

Using join() method of Thread class

The easiest way to deal with our problem is to use join() method of Thread class.

public static void main(String[] args) throws InterruptedException  System.out.println("Start main thread."); Thread firstThread = new Thread(() ->  System.out.println("First thread is running."); >); Thread secondThread = new Thread(() ->  System.out.println("Second thread is running."); >); secondThread.start();; firstThread.start(); secondThread.join(); firstThread.join(); System.out.println("End main thread."); > 

The drawbacks of this way:

Using CountDownLatch

Below is the source code of using CountDownLatch and ExecutorService to manage multiple threads efficiently.

public class ActionService implements Runnable  private CountDownLatch latch; public ActionService(CountDownLatch latch)  this.latch = latch; > public void run()  System.out.println("Start Action Service"); try  Thread.sleep(5000); > catch(InterruptedException ex)  System.out.println(ex); > this.latch.countDown(); > > public static void main(String[] args)  CountDownLatch latch = new CountDownLatch(3); ExecutorService executor = Executors.newFixedThreadPool(3); IntStream.range(0, 3).forEach(item -> xecutor.execute(new ActionService(latch))); executor.shutdown(); try  latch.await(); > catch(InterruptedException ex)  System.out.println(ex); > System.out.println("End of Action Services"); > 

The drawbacks of this way:

Using shutdown(), isTerminated() methods of Executors

From the document of oracle, we have the definition of isTerminated() method:

// Returns true if all tasks have completed following shut down. boolean isTerminated(); 
ExecutorService executor = Executors.newSingleThreadExecutor(); IntStream.range(0, 3).forEach(item -> executor.execute(() -> System.out.println("Thread " + item + "th"))); while (!executor.isTerminated())  // infinite loop > 

Using awaitTermination() method after shutdown() method of Executors

From the document of oracle, we have the definition of awaitTermination() method:

// Blocks until all tasks have completed execution after a shutdown request, or the timeout occurs, or the current thread is interrupted, whichever happens first. boolean awaitTermination(long timeout, TimeUnit unit); 

Below is the source code that using awaitTermination() method and shutdown() method.

ExecutorService executor = Executors.newSingleThreadExecutor(); IntStream.range(0, 3).forEach(item -> executor.execute(() -> System.out.println("Thread " + item + "th"))); executor.shutdown(); try  if (!executor.awaitTermination(50, TimeUnit.SECONDS))  executor.shutdownNow(); > > catch (InterruptedException ex)  System.out.println(ex); > 

Using invokeAll() method of ExecutorService

invokeAll() method returns a list of Future objects after all tasks finish or the timeout expires.

ExecutorService executor = Executors.newFixedThreadPool(3); CollectionCallableVoid>> tasks = new ArrayList<>(); // our task do not need a returned value for (/* iteratare something */)  CallableVoid> task = () ->  // do something // . return null; > tasks.add(task); > try  executor.invokeAll(tasks); > catch(InterruptedException ex)  System.out.println(ex); > 

Using invokeAll() method of ExecutorCompletionService

ExecutorCompletionService uses a queue to store the results in the order they are finished, and invokeAll() method will return a list having the same sequential order as produced by the iterator for the given task list.

public class SleepingCallable implements CallableString>  final String name; final long period; SleepingCallable(final String name, final long period)  this.name = name; this.period = period; > public String call()  try  Thread.sleep(period); > catch (InterruptedException ex)  System.out.println(ex); > return name; > > final ExecutorService pool = Executors.newFixedThreadPool(2); final CompletionServiceString> service = new ExecutorCompletionServiceString>(pool); final List extends CallableString>> callables = Arrays.asList( new SleepingCallable("slow", 5000), new SleepingCallable("quick", 500) ); for (final CallableString> callable : callables)  service.submit(callable); > pool.shutdown(); try  while (!pool.isTerminated())  final FutureString> future = service.take(); System.out.println(future.get()); > > catch (ExecutionException | InterruptedException ex)  System.out.println(ex); > 

Wrapping up

  • Whenever we want to block a thread until another unit of work completes, we should never block infinitely. The await() method, like the Future.get() method, is overloaded to take either no parameters, or a pair of parameters to determine how long to wait. If we use the option of waiting for a specific time, an InterruptedException will be thrown if no response has come in the specific time. If we use the option with no parameters, the await() method will block forever. So if the operation we are waiting on has crashed, and will never return, our application will never progress. Whenever we are waiting on a parallel operation to complete, whether that is in another thread, or, for instance, on a web service to return us some data, we should consider how to react if that operation never return.

Источник

Java – Waiting for Running Threads to Finish

Java concurrency allows running multiple sub-tasks of a task in separate threads. Sometimes, it is necessary to wait until all the threads have finished their execution. In this tutorial, we will learn a few ways to make the current thread wait for the other threads to finish.

1. Using ExecutorService and Future.get()

Java ExecutorService (or ThreadPoolExecutor) helps execute Runnable or Callable tasks asynchronously. Its submit() method returns a Future object that we can use to cancel execution and/or wait for completion. In following example, we have a demo Runnable task. Each task completes in a random time between 0 to 1 second.

public class DemoRunnable implements Runnable < private Integer jobNum; public DemoRunnable(Integer index) < this.jobNum = index; >@SneakyThrows @Override public void run() < Thread.sleep(new Random(0).nextLong(1000)); System.out.println("DemoRunnable completed for index : " + jobNum); >>

We are submitting 10 tasks to the executor service. And then, we invoke Future.get() method on each Future object as received after submitting the task to the executor. The Future.get() waits if necessary for the task to complete, and then retrieves its result.

ExecutorService executor = Executors.newFixedThreadPool(5); List> futures = new ArrayList<>(); for (int i = 1; i f = executor.submit(new DemoRunnable(i)); futures.add(f); > System.out.println("###### All tasks are submitted."); for (Future f : futures) < f.get(); >System.out.println("###### All tasks are completed.");
###### All tasks are submitted. DemoRunnable completed for index : 3 DemoRunnable completed for index : 4 DemoRunnable completed for index : 1 DemoRunnable completed for index : 5 DemoRunnable completed for index : 2 DemoRunnable completed for index : 6 DemoRunnable completed for index : 10 DemoRunnable completed for index : 7 DemoRunnable completed for index : 9 DemoRunnable completed for index : 8 ###### All tasks are completed.
  • the task is cancelled
  • the task execution threw an exception
  • there is an InterruptedException i.e., current thread was interrupted while waiting.

In such a case, we should implement our own logic to handle the exception.

2. Using ExecutorService shutdown() and awaitTermination()

The awaitTermination() method blocks until all tasks have completed execution after a shutdown() request on the executor service. Similar to Future.get(), it can unblock earlier if the timeout occurs, or the current thread is interrupted.

The shutdown() method closes the executor so no new tasks can be submitted, but previously submitted tasks continue execution.

The following method has the complete logic of waiting for all tasks to finish in 1 minute. After that, the executor service will be shut down forcibly using shutdownNow() method.

void shutdownAndAwaitTermination(ExecutorService executorService) < executorService.shutdown(); try < if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) < executorService.shutdownNow(); >> catch (InterruptedException ie) < executorService.shutdownNow(); Thread.currentThread().interrupt(); >>

We can use this method as follows:

ExecutorService executor = Executors.newFixedThreadPool(5); for (int i = 1; i System.out.println("###### All tasks are submitted."); shutdownAndAwaitTermination(executor); System.out.println("###### All tasks are completed.");

3. Using ExecutorService invokeAll()

This approach can be seen as a combination of the previous two approaches. It accepts the tasks as a collection and returns a list of Future objects to retrieve output if necessary. Also, it uses the shutdown and awaits logic for waiting for the tasks to be complete.

In following example, we are using the DemoCallable class that is very similar to DemoRunnable, except it returns an Integer value.

ExecutorService executor = Executors.newFixedThreadPool(10); List tasks = Arrays.asList( new DemoCallable(1), new DemoCallable(2), new DemoCallable(3), new DemoCallable(4), new DemoCallable(5), new DemoCallable(6), new DemoCallable(7), new DemoCallable(8), new DemoCallable(9), new DemoCallable(10)); System.out.println("###### Submitting all tasks."); List> listOfFutures = executor.invokeAll(tasks); shutdownAndAwaitTermination(executor); System.out.println("###### All tasks are completed.");

Note that listOfFutures stores the task outputs in the same order in which we had submitted the tasks to the executor service.

for (Future f : listOfFutures) < System.out.print(f.get() + " "); //Prints 1 2 3 4 5 6 7 8 9 10 >

The CountDownLatch class enables a Java thread to wait until a collection of threads (latch is waiting for) to complete their tasks.

CountDownLatch works by having a counter initialized with a number of threads, which is decremented each time a thread completes its execution. When the count reaches zero, it means all threads have completed their execution, and the main thread waiting on the latch resumes the execution.

In the following example, the main thread is waiting for 3 given services to complete before reporting the final system status. We can read the whole example in CountDownLatch example.

CountDownLatch latch = new CountDownLatch(3); List services = new ArrayList<>(); services.add(new NetworkHealthChecker(latch)); services.add(new CacheHealthChecker(latch)); services.add(new DatabaseHealthChecker(latch)); Executor executor = Executors.newFixedThreadPool(services.size()); for(final BaseHealthChecker s : services) < executor.execute(s); >//Now wait till all health checks are complete latch.await();

In this tutorial, we learned to make an application thread wait for other threads to finish. We learned to use the ExecutorService methods and CountDownLatch class.

Источник

Читайте также:  Code for sms html
Оцените статью