I have these 5 simple thread that run a while loop:
flasherThread = new Thread(new Runnable() {
#Override
public void run() {
while(running.get()) {
// do network stuff
}
}
});
running is declared as private final AtomicBoolean running;.
I have this method:
public void stopFlasherThread() {
running.set(false);
}
My question is by setting the flag to false that stops the thread immediately ? Or do I need to call flasherThread.join() to make sure that the thread has stopped ?
The main issue is that I have 4-5 of these at a time.
So I have a loop such as:
for (int i = 0; i < 5; i++) {
ThreadArrayList.get(i).stopFlasherThread();
ThreadArrayList.get(i).join() // should I do this ?
}
Any help would be great! Thanks
According to the official documentation on join:
The join method allows one thread to wait for the completion of another. If t is a Thread object whose thread is currently executing,
t.join();
causes the current thread to pause execution until t's thread terminates.
So, no... or not necessarily, only if you need the result of the work of that thread to do something. The join will not stop / interrupt the thread, it will wait for it to finish its work. The stopFlasherThread will make the loop stop.
I would advise you to follow a different approach on using threads on Java using ExecutorService. For example:
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<AtomicInteger> futureResult = executor.submit(new Callable<AtomicInteger>() {
#Override
public AtomicInteger call() {
// Here I return a random integer, but you can do your proper calculation
AtomicInteger atomicInteger =
new AtomicInteger(ThreadLocalRandom.current().nextInt());
System.out.println(Thread.currentThread().getName() + " " + atomicInteger);
return atomicInteger;
}
});
// Thread returns result, but continues to execute as it is a single thread pool
try {
System.out.println(Thread.currentThread().getName() + " " + futureResult.get());
} catch (InterruptedException e) {
// Handle exception properly
e.printStackTrace();
} catch (ExecutionException e) {
// Handle exception properly
e.printStackTrace();
}
// Stop all threads
executor.shutdownNow();
There I define an inline class that extends the Callable interface and implement the call method to perform a task in another thread. This returns the result of the computation in the variable futureResult which is a Future. Since executor is a thread pool, it continues to be available to take tasks even though our task here has already been resolved. To finish the whole thread pool loop you can do a executor.shutdownNow().
I'm having trouble getting over 100 threads to run simultaneously. When I do a thread dump, I noticed that many of them are in parked status, i.e.
parking to wait for <0x00000000827e1760> (java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject).
The program runs fine with about 25 threads or less. Is there a way ti identify what's causing the concurrent lock, and/or prevent it? This was running in a fixed pool size of 200 using the Executor service.
Apologies for the lack of code - it's proprietary and there's a lot to be changed to obfuscated it.
Are you using some sort of ThreadPoolExecutor such as the ones provided by java.util.concurrent.Executors class? Perhaps you are facing a case of tasks being finished by silently uncaught exceptions. The dump fragment looks like an inactive pooled thread and one reason to get an inactive thread (which should be active) is an exception throwed up but surrounded by the default thread pool implementation.
LockSupport.park()
In thread pools, THREADS waiting for a TASK are locked out by LockSupport.park();. See java.util.concurrent.locks.AbstractQueuedSynchronizer source from openjdk :
public final void await() throws InterruptedException {
// code omitted
while (!isOnSyncQueue(node)) {
LockSupport.park(this);
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
}
// code omitted
}
It means that the TASK which the THREAD were executing finished (abruptaly or not) and now the thread is waiting for another task to execute (see java.util.concurrent.ThreadPoolExecutor openjdk source):
private Runnable getTask() {
// ...
Runnable r = timed ?
workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
workQueue.take(); <== the thread is blocked here
// ...
}
As one can see, the thread is locked out in the call workQueue.take();.
Thus, shortly, threads in "parked status" are just waiting for new tasks after the previous ones have finished.
Why does my task is no longer running?
The most reasonable cause of a finished task is the regular end of the run(). The task flow finishes and then the task is released by the respective owner thread. Once the thread releases the task, it is ready to execute another task as long there is one.
A straightforward way to check this scenario is by logging something in the end of the run() method:
class MyRunnable implements Runnable {
public void run() {
while(/*some condition*/) {
// do my things
}
log.info("My Runnable has finished for now!");
}
}
If log a message is not enough you can call a method of another object instead.
Exceptions under the wood
Another (most) probable cause is an uncaught exception thrown during the task execution. Within a thread pool, an unchecked exception like this will abruptaly stop the method execution and (surprisely) be swallowed into a java.util.concurrent.FutureTask object. In order to avoid things like this, I use the following idiom:
class MyRunnable implements Runnable {
public void run() {
while(/*some condition*/) {
try {
// do my things
} catch (Throwable throwable) {
handle(throwable);
}
}
log.info("My Runnable has finished for now!");
}
private void handle(Throwable throwable) {
// ...
}
}
or depending on the logic/performance requirements I also use:
public void run() {
try {
while(/*some condition*/) {
// do my things
}
} catch (Throwable throwable) {
handle(throwable);
}
System.out.println("My Runnable has finished for now!");
}
The code below exemplify the issues commented here in action:
package mypocs;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;
public class ExceptionSwallowingInThreadPoolsPoC {
public static void main(String[] args) {
ThreadPoolExecutor threadPoolExecutor = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
final Object LOCK = new Object();
threadPoolExecutor.submit(() -> {
while (true) {
synchronized (LOCK) {
System.out.println("Thread 'A' never ends");
}
Thread.sleep(1000L);
}
});
threadPoolExecutor.submit(() -> {
int lifespan = 3;
while (lifespan > 0) {
synchronized (LOCK) {
System.out.println("Thread 'B' is living for " + lifespan + " seconds");
}
lifespan--;
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Thread 'B' finished");
});
threadPoolExecutor.submit(() -> {
int lifespan = 3;
while (lifespan > 0) {
synchronized (LOCK) {
System.out.println("Thread 'C' is living for " + lifespan + " seconds");
}
lifespan--;
if (lifespan < 1) {
throw new RuntimeException("lifespan reached zero");
}
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Thread 'C' finished");
});
while (true) {
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (LOCK) {
System.out.println("==== begin");
System.out.println("getActiveCount: " + threadPoolExecutor.getActiveCount());
System.out.println("getCompletedTaskCount: " + threadPoolExecutor.getCompletedTaskCount());
System.out.println("getPoolSize: " + threadPoolExecutor.getPoolSize());
System.out.println("==== end");
}
}
}
}
The code should output something like:
Thread 'A' never ends
Thread 'B' is living for 3 seconds
Thread 'C' is living for 3 seconds
Thread 'C' is living for 2 seconds
==== begin
getActiveCount: 3
getCompletedTaskCount: 0
getPoolSize: 3
==== end
Thread 'B' is living for 2 seconds
Thread 'A' never ends
==== begin
getActiveCount: 3
getCompletedTaskCount: 0
getPoolSize: 3
==== end
Thread 'C' is living for 1 seconds
Thread 'B' is living for 1 seconds
Thread 'A' never ends
Thread 'B' finished
==== begin
getActiveCount: 1
getCompletedTaskCount: 2
getPoolSize: 3
==== end
Thread 'A' never ends
Thread 'A' never ends
...
The class (ConditionObject) you are referring to is used to lock objects from being accessed concurrently by multiple threads. The Javadoc doesn't describe the thread state you mention, but here is my guess:
Your locked object is being blocked by one thread so long, that the other threads start to pile up on the lock. Once the thread holding the lock releases it, the next thread continues the aquire the lock. Until that new thread has done his work, new threads pile up behing the lock.
If my guess is right, then could:
reduce the time that each thread spends in the lock, or
distribute the threads on different locked things (if your problem permits that), or
you use an implementation that doesn't require locking.
Without knowing your problem domain, I hope that the information above is enough to point you into some direction that might be of help for you.
Lock sharedLock = new ReentrantLock();
Condition condition = lock.newCondition();
main thread:
sharedLock.lock();
childThread.start();
condition.await(5, TimeUnit.SECONDS);
sharedLock.unlock();
child thread:
sharedLock.lock();
//do something, may take a long time
Thread.sleep(10);// sleep to simulate a long execution
condition.signal();
sharedLock.unlock();
Suppose child thread send a network request and wait for response, I want main thread wait at most 5 seconds, if timeout, retry the request. but when the await() timeout, it cannot acquire lock because child thread still hold it, so it still wait the lock until child thread release it, which takes 10 seconds.
How can I achieve my requirement that main thread wait child thread's signal, but have a bounded timeout?
This is not how your are supposed to do it, you are supposed to:
Create an ExecutorService (thread pool) for that you should check the methods of the class Executors to choose the best one in your case but Executors.newFixedThreadPool is a good start
Submit your task as a FutureTask to the thread pool
Then call get with a timeout
Manage properly the TimeoutException
Here is how it could be done:
// Total tries
int tries = 3;
// Current total of tries
int tryCount = 1;
do {
// My fake task to execute asynchronously
FutureTask<Void> task = new FutureTask<>(
() -> {
Thread.sleep(2000);
return null;
}
);
// Submit the task to the thread pool
executor.submit(task);
try {
// Wait for a result during at most 1 second
task.get(1, TimeUnit.SECONDS);
// I could get the result so I break the loop
break;
} catch (TimeoutException e) {
// The timeout has been reached
if (tryCount++ == tries) {
// Already tried the max allowed so we throw an exception
throw new RuntimeException(
String.format("Could execute the task after %d tries", tries),
e
);
}
}
} while (true);
How can I achieve my requirement that main thread wait child thread's
signal, but have a bounded timeout?
Here is how you can achieve your requirements:
Main Thread:
lock.lock();
try {
childThread.start();
condition.await(5, TimeUnit.SECONDS);
} finally {
sharedLock.lock();
}
The child thread:
try {
//do something, may take a long time
Thread.sleep(10);// sleep to simulate a long execution
} finally {
// Here we notify the main thread that the task is complete whatever
// the task failed or not
lock.lock();
try {
condition.signal();
} finally {
lock.unlock();
}
}
As you can see to work, the task must not be performed within the critical section, we only acquire the lock to notify the main thread nothing more. Otherwise if you execute the task within the critical section after the timeout the main thread will still need to acquire the lock once again and since the lock is actually owned by the child thread, it will need to wait anyway until the end of the task which makes the timeout totally useless.
NB: I renamed sharedLock to lock as a ReentrantLock is an exclusive lock not as shared lock, if you need a shared lock check the class Semaphore to define the total amount of permits.
Your code can be simplified with intrinsic lock.
Object sharedObj = new Object();
main thread:
synchronized (sharedObj) {
int retryCount = 0;
while (retryCount < maxRetry) {
sharedObj.wait(5000);
retryCount++;
}
}
child thread:
synchronized (sharedObj) {
//do something, may take a long time
Thread.sleep(10);// sleep to simulate a long execution
sharedObj.notify();
}
java condition await timeout but can't return
That's because the lock must be released so wait/await can return. So your child thread should be like:
//do something, may take a long time
Thread.sleep(10);// sleep to simulate a long execution
synchronized (sharedObj) {
sharedObj.notify();
}
Java's wait/notify is usually used to solve producer-consumer problem. And usually sharedObj shouldn't be holded for too long. Then your main thread can hold the lock again when the wait timeout.
Take a look at an in-production example: hadoop/hdfs/DFSOutputStream.java
The logic is simple, the producer creates packet and put it in dataQueue
// takes a long time to create packet
synchronized (dataQueue) {
dataQueue.addLast(packet);
dataQueue.notifyAll();
}
The consumer wait while dataQueue is empty:
synchronized (dataQueue) {
while ((!shouldStop() && dataQueue.size() == 0 &&... ) {
try {
dataQueue.wait(timeout);
} catch (InterruptedException e) {
LOG.warn("Caught exception", e);
}
doSleep = false;
now = Time.monotonicNow();
}
As you can see, the dataQueue are unlocked for most of the time!
How can I achieve my requirement that main thread wait child thread's signal, but have a bounded timeout?
If your child thread are mostly in a loop, your Main thread can set a isRunning flag to make child thread stop by itself. If your child thread are mostly blocking by an I/O operation, your Main thread can interrupt the child thread.
The sharedObj is used for coordination and protects sharedObj. If there's other resources should be protected, you have 2 choices:
1. If the operation on the resource is quick, like ackQueue in DFSOutputStream.java, protect it together inside the sharedObj.
2. If the operation on the resource is time-consuming, do it and protect it outside the sharedObj.
The valid confusion in the question is because the "Thread.sleep(10)" is done inside the lock block. When await(long time, TimeUnit unit) has to return because of timeout, it still needs the lock. So, as suggested in the other answer the long running task should not be inside the lock for it to work properly.
But it would be nice to have proper documentation stressing this fact. For example, if we await(5, TimeUnit.SECONDS) i.e wait for 5 seconds and the lock is available 10 seconds after the call, it will still return false even though the lock is available now at the moment of return.
I want to stop a running thread immediately. Here is my code:
Class A :
public class A() {
public void methodA() {
For (int n=0;n<100;n++) {
//Do something recursive
}
//Another for-loop here
//A resursive method here
//Another for-loop here
finishingMethod();
}
}
Class B:
public class B() {
public void runEverything() {
Runnable runnable = new Runnable() {
#Override
public void run() {
try {
Thread.sleep(1000);
A a = new A();
a.methodA();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread thread = new Thread(runnable);
thread.start();
}
My problem is that i need to be able to stop the thread in Class B even before the thread is finished. I've tried interrupt() method, but that doesn't stop my thread. I've also heard about using shared variable as a signal to stop my thread, but I think with long recursive and for-loop in my process, shared-variable will not be effective.
Any idea ?
Thanks in advance.
Thread.interrupt will not stop your thread (unless it is in the sleep, in which case the InterruptedException will be thrown). Interrupting basically sends a message to the thread indicating it has been interrupted but it doesn't cause a thread to stop immediately.
When you have long looping operations, using a flag to check if the thread has been cancelled is a standard approach. Your methodA can be modified to add that flag, so something like:
// this is a new instance variable in `A`
private volatile boolean cancelled = false;
// this is part of your methodA
for (int n=0;n<100;n++) {
if ( cancelled ) {
return; // or handle this however you want
}
}
// each of your other loops should work the same way
Then a cancel method can be added to set that flag
public void cancel() {
cancelled = true;
}
Then if someone calls runEverything on B, B can then just call cancel on A (you will have to extract the A variable so B has a reference to it even after runEverything is called.
I think you should persevere with using Thread.interrupt(). But what you need to do to make it work is to change the methodA code to do something like this:
public void methodA() throws InterruptedException {
for (int n=0; n < 100; n++) {
if (Thread.interrupted) {
throw new InterruptedException();
}
//Do something recursive
}
// and so on.
}
This is equivalent declaring and using your own "kill switch" variable, except that:
many synchronization APIs, and some I/O APIs pay attention to the interrupted state, and
a well-behaved 3rd-party library will pay attention to the interrupted state.
Now it is true that a lot of code out there mishandles InterruptedException; e.g. by squashing it. (The correct way to deal with an InterruptedException is to either to allow it to propagate, or call Thread.interrupt() to set the flag again.) However, the flip side is that that same code would not be aware of your kill switch. So you've got a problem either way.
You can check the status of the run flag as part of the looping or recursion. If there's a kill signal (i.e. run flag is set false), just return (after whatever cleanup you need to do).
There are some other possible approaches:
1) Don't stop it - signal it to stop with the Interrupted flag, set its priority to lowest possible and 'orphan' the thread and any data objects it is working on. If you need the operation that is performed by this thread again, make another one.
2) Null out, corrupt, rename, close or otherwise destroy the data it is working on to force the thread to segfault/AV or except in some other way. The thread can catch the throw and check the Interrupted flag.
No guarantees, sold as seen...
From main thread letsvsay someTask() is called and t1.interrput is being called..
t1.interrupt();
}
private static Runnable someTask(){
return ()->{
while(running){
try {
if(Thread.interrupted()){
throw new InterruptedException( );
}
// System.out.println(i + " the current thread is "+Thread.currentThread().getName());
// Thread.sleep( 2000 );
} catch (Exception e) {
System.out.println(" the thread is interrputed "+Thread.currentThread().getName());
e.printStackTrace();
break;
}
}
o/P:
java.lang.InterruptedException
at com.barcap.test.Threading.interrupt.ThreadT2Interrupt.lambda$someTask$0(ThreadT2Interrupt.java:32)
at java.lang.Thread.run(Thread.java:748)
the thread is interrputed Thread-0
Only t1.interuuption will not be enough .this need check the status of Thread.interrupted() in child thread.
I'm writing an application that has 5 threads that get some information from web simultaneously and fill 5 different fields in a buffer class.
I need to validate buffer data and store it in a database when all threads finished their job.
How can I do this (get alerted when all threads finished their work) ?
The approach I take is to use an ExecutorService to manage pools of threads.
ExecutorService es = Executors.newCachedThreadPool();
for(int i=0;i<5;i++)
es.execute(new Runnable() { /* your task */ });
es.shutdown();
boolean finished = es.awaitTermination(1, TimeUnit.MINUTES);
// all tasks have finished or the time has been reached.
You can join to the threads. The join blocks until the thread completes.
for (Thread thread : threads) {
thread.join();
}
Note that join throws an InterruptedException. You'll have to decide what to do if that happens (e.g. try to cancel the other threads to prevent unnecessary work being done).
Have a look at various solutions.
join() API has been introduced in early versions of Java. Some good alternatives are available with this concurrent package since the JDK 1.5 release.
ExecutorService#invokeAll()
Executes the given tasks, returning a list of Futures holding their status and results when everything is completed.
Refer to this related SE question for code example:
How to use invokeAll() to let all thread pool do their task?
CountDownLatch
A synchronization aid that allows one or more threads to wait until a set of operations being performed in other threads completes.
A CountDownLatch is initialized with a given count. The await methods block until the current count reaches zero due to invocations of the countDown() method, after which all waiting threads are released and any subsequent invocations of await return immediately. This is a one-shot phenomenon -- the count cannot be reset. If you need a version that resets the count, consider using a CyclicBarrier.
Refer to this question for usage of CountDownLatch
How to wait for a thread that spawns it's own thread?
ForkJoinPool or newWorkStealingPool() in Executors
Iterate through all Future objects created after submitting to ExecutorService
Wait/block the Thread Main until some other threads complete their work.
As #Ravindra babu said it can be achieved in various ways, but showing with examples.
java.lang.Thread.join() Since:1.0
public static void joiningThreads() throws InterruptedException {
Thread t1 = new Thread( new LatchTask(1, null), "T1" );
Thread t2 = new Thread( new LatchTask(7, null), "T2" );
Thread t3 = new Thread( new LatchTask(5, null), "T3" );
Thread t4 = new Thread( new LatchTask(2, null), "T4" );
// Start all the threads
t1.start();
t2.start();
t3.start();
t4.start();
// Wait till all threads completes
t1.join();
t2.join();
t3.join();
t4.join();
}
java.util.concurrent.CountDownLatch Since:1.5
.countDown() « Decrements the count of the latch group.
.await() « The await methods block until the current count reaches zero.
If you created latchGroupCount = 4 then countDown() should be called 4 times to make count 0. So, that await() will release the blocking threads.
public static void latchThreads() throws InterruptedException {
int latchGroupCount = 4;
CountDownLatch latch = new CountDownLatch(latchGroupCount);
Thread t1 = new Thread( new LatchTask(1, latch), "T1" );
Thread t2 = new Thread( new LatchTask(7, latch), "T2" );
Thread t3 = new Thread( new LatchTask(5, latch), "T3" );
Thread t4 = new Thread( new LatchTask(2, latch), "T4" );
t1.start();
t2.start();
t3.start();
t4.start();
//latch.countDown();
latch.await(); // block until latchGroupCount is 0.
}
Example code of Threaded class LatchTask. To test the approach use joiningThreads();
and latchThreads(); from main method.
class LatchTask extends Thread {
CountDownLatch latch;
int iterations = 10;
public LatchTask(int iterations, CountDownLatch latch) {
this.iterations = iterations;
this.latch = latch;
}
#Override
public void run() {
String threadName = Thread.currentThread().getName();
System.out.println(threadName + " : Started Task...");
for (int i = 0; i < iterations; i++) {
System.out.println(threadName + " : " + i);
MainThread_Wait_TillWorkerThreadsComplete.sleep(1);
}
System.out.println(threadName + " : Completed Task");
// countDown() « Decrements the count of the latch group.
if(latch != null)
latch.countDown();
}
}
CyclicBarriers A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point.CyclicBarriers are useful in programs involving a fixed sized party of threads that must occasionally wait for each other. The barrier is called cyclic because it can be re-used after the waiting threads are released.
CyclicBarrier barrier = new CyclicBarrier(3);
barrier.await();
For example refer this Concurrent_ParallelNotifyies class.
Executer framework: we can use ExecutorService to create a thread pool, and tracks the progress of the asynchronous tasks with Future.
submit(Runnable), submit(Callable) which return Future Object. By using future.get() function we can block the main thread till the working threads completes its work.
invokeAll(...) - returns a list of Future objects via which you can obtain the results of the executions of each Callable.
Find example of using Interfaces Runnable, Callable with Executor framework.
#See also
Find out thread is still alive?
Apart from Thread.join() suggested by others, java 5 introduced the executor framework. There you don't work with Thread objects. Instead, you submit your Callable or Runnable objects to an executor. There's a special executor that is meant to execute multiple tasks and return their results out of order. That's the ExecutorCompletionService:
ExecutorCompletionService executor;
for (..) {
executor.submit(Executors.callable(yourRunnable));
}
Then you can repeatedly call take() until there are no more Future<?> objects to return, which means all of them are completed.
Another thing that may be relevant, depending on your scenario is CyclicBarrier.
A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point. CyclicBarriers are useful in programs involving a fixed sized party of threads that must occasionally wait for each other. The barrier is called cyclic because it can be re-used after the waiting threads are released.
Another possibility is the CountDownLatch object, which is useful for simple situations : since you know in advance the number of threads, you initialize it with the relevant count, and pass the reference of the object to each thread.
Upon completion of its task, each thread calls CountDownLatch.countDown() which decrements the internal counter. The main thread, after starting all others, should do the CountDownLatch.await() blocking call. It will be released as soon as the internal counter has reached 0.
Pay attention that with this object, an InterruptedException can be thrown as well.
You do
for (Thread t : new Thread[] { th1, th2, th3, th4, th5 })
t.join()
After this for loop, you can be sure all threads have finished their jobs.
Store the Thread-objects into some collection (like a List or a Set), then loop through the collection once the threads are started and call join() on the Threads.
You can use Threadf#join method for this purpose.
Although not relevant to OP's problem, if you are interested in synchronization (more precisely, a rendez-vous) with exactly one thread, you may use an Exchanger
In my case, I needed to pause the parent thread until the child thread did something, e.g. completed its initialization. A CountDownLatch also works well.
I created a small helper method to wait for a few Threads to finish:
public static void waitForThreadsToFinish(Thread... threads) {
try {
for (Thread thread : threads) {
thread.join();
}
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
An executor service can be used to manage multiple threads including status and completion. See http://programmingexamples.wikidot.com/executorservice
try this, will work.
Thread[] threads = new Thread[10];
List<Thread> allThreads = new ArrayList<Thread>();
for(Thread thread : threads){
if(null != thread){
if(thread.isAlive()){
allThreads.add(thread);
}
}
}
while(!allThreads.isEmpty()){
Iterator<Thread> ite = allThreads.iterator();
while(ite.hasNext()){
Thread thread = ite.next();
if(!thread.isAlive()){
ite.remove();
}
}
}
I had a similar problem and ended up using Java 8 parallelStream.
requestList.parallelStream().forEach(req -> makeRequest(req));
It's super simple and readable.
Behind the scenes it is using default JVM’s fork join pool which means that it will wait for all the threads to finish before continuing. For my case it was a neat solution, because it was the only parallelStream in my application. If you have more than one parallelStream running simultaneously, please read the link below.
More information about parallel streams here.
The existing answers said could join() each thread.
But there are several ways to get the thread array / list:
Add the Thread into a list on creation.
Use ThreadGroup to manage the threads.
Following code will use the ThreadGruop approach. It create a group first, then when create each thread specify the group in constructor, later could get the thread array via ThreadGroup.enumerate()
Code
SyncBlockLearn.java
import org.testng.Assert;
import org.testng.annotations.Test;
/**
* synchronized block - learn,
*
* #author eric
* #date Apr 20, 2015 1:37:11 PM
*/
public class SyncBlockLearn {
private static final int TD_COUNT = 5; // thread count
private static final int ROUND_PER_THREAD = 100; // round for each thread,
private static final long INC_DELAY = 10; // delay of each increase,
// sync block test,
#Test
public void syncBlockTest() throws InterruptedException {
Counter ct = new Counter();
ThreadGroup tg = new ThreadGroup("runner");
for (int i = 0; i < TD_COUNT; i++) {
new Thread(tg, ct, "t-" + i).start();
}
Thread[] tArr = new Thread[TD_COUNT];
tg.enumerate(tArr); // get threads,
// wait all runner to finish,
for (Thread t : tArr) {
t.join();
}
System.out.printf("\nfinal count: %d\n", ct.getCount());
Assert.assertEquals(ct.getCount(), TD_COUNT * ROUND_PER_THREAD);
}
static class Counter implements Runnable {
private final Object lkOn = new Object(); // the object to lock on,
private int count = 0;
#Override
public void run() {
System.out.printf("[%s] begin\n", Thread.currentThread().getName());
for (int i = 0; i < ROUND_PER_THREAD; i++) {
synchronized (lkOn) {
System.out.printf("[%s] [%d] inc to: %d\n", Thread.currentThread().getName(), i, ++count);
}
try {
Thread.sleep(INC_DELAY); // wait a while,
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.printf("[%s] end\n", Thread.currentThread().getName());
}
public int getCount() {
return count;
}
}
}
The main thread will wait for all threads in the group to finish.
I had similar situation , where i had to wait till all child threads complete its execution then only i could get the status result for each of them .. hence i needed to wait till all child thread completed.
below is my code where i did multi-threading using
public static void main(String[] args) {
List<RunnerPojo> testList = ExcelObject.getTestStepsList();//.parallelStream().collect(Collectors.toList());
int threadCount = ConfigFileReader.getInstance().readConfig().getParallelThreadCount();
System.out.println("Thread count is : ========= " + threadCount); // 5
ExecutorService threadExecutor = new DriverScript().threadExecutor(testList, threadCount);
boolean isProcessCompleted = waitUntilCondition(() -> threadExecutor.isTerminated()); // Here i used waitUntil condition
if (isProcessCompleted) {
testList.forEach(x -> {
System.out.println("Test Name: " + x.getTestCaseId());
System.out.println("Test Status : " + x.getStatus());
System.out.println("======= Test Steps ===== ");
x.getTestStepsList().forEach(y -> {
System.out.println("Step Name: " + y.getDescription());
System.out.println("Test caseId : " + y.getTestCaseId());
System.out.println("Step Status: " + y.getResult());
System.out.println("\n ============ ==========");
});
});
}
Below method is for distribution of list with parallel proccessing
// This method will split my list and run in a parallel process with mutliple threads
private ExecutorService threadExecutor(List<RunnerPojo> testList, int threadSize) {
ExecutorService exec = Executors.newFixedThreadPool(threadSize);
testList.forEach(tests -> {
exec.submit(() -> {
driverScript(tests);
});
});
exec.shutdown();
return exec;
}
This is my wait until method: here you can wait till your condition satisfies within do while loop . in my case i waited for some max timeout .
this will keep checking until your threadExecutor.isTerminated() is true with polling period of 5 sec.
static boolean waitUntilCondition(Supplier<Boolean> function) {
Double timer = 0.0;
Double maxTimeOut = 20.0;
boolean isFound;
do {
isFound = function.get();
if (isFound) {
break;
} else {
try {
Thread.sleep(5000); // Sleeping for 5 sec (main thread will sleep for 5 sec)
} catch (InterruptedException e) {
e.printStackTrace();
}
timer++;
System.out.println("Waiting for condition to be true .. waited .." + timer * 5 + " sec.");
}
} while (timer < maxTimeOut + 1.0);
return isFound;
}
Use this in your main thread: while(!executor.isTerminated());
Put this line of code after starting all the threads from executor service. This will only start the main thread after all the threads started by executors are finished. Make sure to call executor.shutdown(); before the above loop.