This post shows an example of a bad practice I saw in one of my Java projects seven years ago. It also has a naive implementation of concurrency in Java, wherein it waits for all threads to complete. Moreover, it tracks the number of started, completed, and in-progress threads. Since the codes exhibit malpractice, I do not recommend using these codes. Alternatively, there are better solutions already available in the Java SDK.
A Wait Bean For All Threads To Complete
This class keeps count of expected, and completed threads count.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | package com.karlsangabriel.waitallthreads; public class ThreadWaitBean { private int expectedCount; private int actualCount; private boolean hasErrors; public synchronized int getExpectedCount() { return expectedCount; } public synchronized void setExpectedCount(int expectedCount) { this.expectedCount = expectedCount; } public synchronized int getActualCount() { return actualCount; } public synchronized void setActualCount(int actualCount) { this.actualCount = actualCount; } public synchronized boolean isHasErrors() { return hasErrors; } public synchronized void setHasErrors(boolean hasErrors) { this.hasErrors = hasErrors; } public synchronized void executionComplete() { this.actualCount++; } public synchronized boolean isDone() { if(this.actualCount == this.expectedCount) { return true; } return false; } } |
The Thread class
This class represents a task. It sleeps for 10 seconds to simulate heavy processing and runs the executionComplete method. Therefore, all our Java threads will wait 10 seconds before they are complete.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | package com.karlsangabriel.waitallthreads; public class ThreadTest implements Runnable { private ThreadWaitBean waitBean; public ThreadTest(ThreadWaitBean bean) { this.waitBean = bean; } public void run() { System.out.println( this.toString() + " task has started"); try { Thread.sleep(10000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(this.toString() + " completing task"); this.waitBean.executionComplete(); this.waitBean = null; } } |
Main Class That Starts All Java Threads
The codes need to know the number of Java threads to process or complete. The ThreadWaitBean keeps this number of started threads compared to the number of threads actually completed. The basic idea is that each thread has access to a single ThreadWaitBean object. Right before a thread ends, it runs the executionComplete method. That method adds 1 to the number of threads actually completed.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 | package com.karlsangabriel.waitallthreads; public class WaitAllThreadsMain { public static void main(String[] args) { ThreadWaitBean waitBean = new ThreadWaitBean(); waitBean.setExpectedCount(5); for(int i = 0; i < waitBean.getExpectedCount(); i++) { Thread t = new Thread(new ThreadTest(waitBean)); t.start(); } while(!waitBean.isDone()) { try { Thread.sleep(1000); } catch (InterruptedException e) { Thread.currentThread.interrupt(); e.printStackTrace(); } System.out.println( "Parent thread awaits Threads completion"); } System.out.println("All Threads completed at this point"); } } |
Demo and Output
We will get the following in our console if we run the codes.