I have multiple threads waiting on a notify() from a tick clock. One of these threads should wait for the rest to execute before it runs. Normally I believe the way to do this would be to use a join() but in this case the Threads never die, they just wait() for the next tick signal. Is there a way to ensure that Thread "z" will always wake up after Threads "a-y" upon receiving the same notify()?
EDIT: Added code for example
Thread 1-4:
while(running) {
synchronized(tickSignal){
/*
* Code in this section adds objects to a queue that Thread 5 reads
* It also has other code that must be executed every tick
*/
tickSignal.wait();
}
}
Thread 5:
while(running) {
synchronized(tickSignal) {
/*
* Code in this section reads all the objects added to the queue by T1-4
* It also has other code that must be executed every tick
*/
tickSignal.wait();
}
}
Tick Clock:
while(running) {
synchronized(tickSignal){
tickSignal.notifyAll();
}
Thread.sleep(1000);
}
There are also other threads monitoring tickSignal that do not interact with Thread 5 at all.
If I understand it correctly, there are N tasks to be executed when a tick signal is given. The N-th task can only start after the first N-1 tasks have been completed. Since the notifyAll() function notifies Threads in an unordered way, you have to extend your code slightly.
First of all, I think this construction is not a safe construction. Think about the case that executing the code in a Thread takes longer than 1 second. In that case, the Thread will not be notified at the next tick signal, since it did not yet reach the wait() function. However, let's for the moment assume that this will not occur.
Since the N-th task can only be executed after the first N-1 tasks are completed, it has to wait and has to be notified when the first N-1 tasks are actually completed.
In order to count the number of completed tasks, you can use a Thread-safe AtomicInteger counter. Each time a task is completed, the counter increases with 1. When the counter reaches the value N-1, it notifies the N-th Thread and the value is reset to 0.
To give you the code:
// Besides a tickSignal, we also need a finalThreadSignal, which
// will be notified when the first N-1 Threads are finished.
private Object tickSignal = new Object();
private Object finalThreadSignal = new Object();
private AtomicInteger completedThreadsCounter = new AtomicInteger(0);
Thread 1-(N-1):
while (running) {
synchronized (tickSignal) {
try {
tickSignal.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
// Code
// Task finished
int counter = completedThreadsCounter.incrementAndGet();
if (counter == N-1) {
// Notify Thread N when the first N-1 tasks are finished
synchronized (finalThreadSignal) {
finalThreadSignal.notify();
}
// Reset the finished Threads counter and wait for the next tick signal
completedThreadsCounter.set(0);
}
}
}
Thread N:
while (running) {
// Here we synchronize on the signal that will be given when
// the first N-1 Threads are finished
synchronized (finalThreadSignal) {
try {
finalThreadSignal.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
// Execute final Thread code
}
}
As I already indicated, this construction will fail if the execution time in a Thread is larger than the time between two ticks. Please let me know exactly what the problem is to give you are more suitable answer.
Related
I have 5 threads (5 instances of one Runnable class) starting approximately at the same time (using CyclicBarrier) and I need to stop them all as soon as one of them finished.
Currently, I have a static volatile boolean field threadsOver that I'm setting to true at the end of doSomething(), the method that run() is calling.
private static final CyclicBarrier barrier = new CyclicBarrier(5);
private static volatile boolean threadsOver;
#Override
public void run() {
try {
/* waiting for all threads to have been initialised,
so as to start them at the same time */
barrier.await();
doSomething();
} catch (InterruptedException | BrokenBarrierException e) {
e.printStackTrace();
}
}
public void doSomething() {
// while something AND if the threads are not over yet
while (someCondition && !threadsOver) {
// some lines of code
}
// if the threads are not over yet, it means I'm the first one to finish
if (!threadsOver) {
// so I'm telling the other threads to stop
threadsOver = true;
}
}
The problem with that code is that the code in doSomething() is executing too fast and as a result, the threads that finish after the first one are already over by the time that the first thread noticed them.
I tried adding some delay in doSomething() using Thread.sleep(), which reduced the number of threads which finished even after the first one, but there are still some times where 2 or 3 threads will finish execution completely.
How could I make sure that when one thread is finished, all of the others don't execute all the way to the end?
First where I copied code snippets from: https://www.baeldung.com/java-executor-service-tutorial .
As you have 5 tasks of which every one can produce the result, I prefer Callable, but Runnable with a side effect is handled likewise.
The almost simultaneous start, the Future task aspect, and picking the first result can be done by invokeAny below:
Callable<Integer> callable1 = () -> {
return 1*2*3*5*7/5;
};
List<Callable<Integer>> callables = List.of(callable1, callable2, ...);
ExecutorService executorService = new ThreadPoolExecutor(5);
Integer results = executorService.invokeAny(callables);
executorService.shutDown();
invokeAny() assigns a collection of tasks to an ExecutorService, causing each to run, and returns the result of a successful execution of one task (if there was a successful execution).
Firstly I think this probably more of a problem with my design and my lack of knowledge for what terms I should be searching for. On to the problem.
Say I have 3 threads (t1, t2, t3).
These threads have access to a thread that implements a semaphore(sem) with 1 permit and is fair (giving FIFO to threads that queue), and a thread that implements a timer (timer) which increments a int (time) every 20ms.
If all 3 threads arrived here in their code at the same time and waited for the timer to increment 6 units before continuing.
//In a thread t_ class
int timeInitial = timer.getTime();
while((timeInitial+6)>timer.getTime()) {
//Sleeps for 10ms to ensure it doesn't miss the timers 20ms
increments
try {
sleep(10);
}
catch (InterruptedException e) {
}
}
//Thread joins queue for the singular permit
sem.aquire();
//In the sem class
public void acquire() {
try {
semaphore.acquire();
}
catch (InterruptedException e) {
}
}
//In the timer class, timer functionality. Also has get and set method for time
#Override
public void run() {
while(processes > 0) {
try {
sleep(21);
time++;
}
catch (InterruptedException e) {
}
}
}
What I would like to happen is if multiple threads attempt to acquire a permit at the same timer time they would in attempt to in order of lowest to highest (t1, t2, t3). Where now they would join the queue in a seemingly random order.
Note, that if say t2 and t3 were already queued for the permit at time=6 and t1 came at time=7, it would not jump the queue but only compare with other additions at time=7 before queuing (t2, t3, t1).
I'm not bound to use a semaphore here, is just my best knowledge of tools to approach this problem.
I think you want to have your threads go into a priority queue, which will be sorted by arrival time, then priority when the time is the same. Once a thread adds itself to this priority queue, it enters a wait(). You would need a mechanism that would, at the right time, wake up all threads in the queue. On waking up, they would each check to see whether they are the head of the queue - the ones that are not, go back to wait(), and the one that is, removes itself from the queue and goes and does its thing. Maybe the right time is each time the thread that was selected completes its work, or goes back into the queue?
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.
Suppose that I have an arraylist called myList of threads all of which are created with an instance of the class myRunnable implementing the Runnable interface, that is, all the threads share the same code to execute in the run() method of myRunnable. Now suppose that I have another single thread called singleThread that is created with an instance of the class otherRunnable implementing the Runnable interface.
The synchornization challenge I have to resolve for these threads is the following: I need all of the threads in myList to execute their code until certain point. Once reached this point, they shoud sleep. Once all and only all of the threads in myList are sleeping, then singleThread should be awakened (singleThread was already asleep). Then singleThread execute its own stuff, and when it is done, it should sleep and all the threads in myList should be awakened. Imagine that the codes are wrapped in while(true)'s, so this process must happen again and again.
Here is an example of the situation I've just described including an attempt of solving the synchronization problem:
class myRunnable extends Runnable
{
public static final Object lock = new Object();
static int count = 0;
#override
run()
{
while(true)
{
//do stuff
barrier();
//do stuff
}
}
void barrier()
{
try {
synchronized(lock) {
count++;
if (count == Program.myList.size()) {
count = 0;
synchronized(otherRunnable.lock) {
otherRunnable.lock.notify();
}
}
lock.wait();
}
} catch (InterruptedException ex) {}
}
}
class otherRunnable extend Runnable
{
public static final Object lock = new Object();
#override
run()
{
while(true)
{
try {
synchronized(lock) {
lock.wait();
} catch (InterruptedException ex) {}
// do stuff
try {
synchronized(myRunnable.lock) {
myRunnable.notifyAll();
}
}
}
}
class Program
{
public static ArrayList<Thread> myList;
public static void main (string[] args)
{
myList = new ArrayList<Thread>();
for(int i = 0; i < 10; i++)
{
myList.add(new Thread(new myRunnable()));
myList.get(i).start();
}
new Thread(new OtherRunnable()).start();
}
}
Basically my idea is to use a counter to make sure that threads in myList just wait except the last thread incrementing the counter, which resets the counter to 0, wakes up singleThread by notifying to its lock, and then this last thread goes to sleep as well by waiting to myRunnable.lock. In a more abstract level, my approach is to use some sort of barrier for threads in myList to stop their execution in a critical point, then the last thread hitting the barrier wakes up singleThread and goes to sleep as well, then singleThread makes its stuff and when finished, it wakes up all the threads in the barrier so they can continue again.
My problem is that there is a flaw in my logic (probably there are more). When the last thread hitting the barrier notifies otherRunnable.lock, there is a chance that an immediate context switch could occur, giving the cpu to singleThread, before the last thread could execute its wait on myRunnable.lock (and going to sleep). Then singleThread would execute all its stuff, would execute notifyAll on myRunnable.lock, and all the threads in myList would be awakened except the last thread hitting the barrier because it has not yet executed its wait command. Then, all those threads would do their stuff again and would hit the barrier again, but the count would never be equal to myList.size() because the last thread mentioned earlier would be eventually scheduled again and would execute wait. singleThread in turn would also execute wait in its first line, and as a result we have a deadlock, with everybody sleeping.
So my question is: what would be a good way to synchronize these threads in order to achieve the desired behaviour described before but at the same time in a way safe of deadlocks??
Based on your comment, sounds like a CyclicBarrier would fit your need exactly. From the docs (emphasis mine):
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.
Unfortunately, I haven't used them myself, so I can't give you specific pointers on them. I think the basic idea is you construct your barrier using the two-argument constructor with the barrierAction. Have your n threads await() on this barrier after this task is done, after which barrierAction is executed, after which the n threads will continue.
From the javadoc for CyclicBarrier#await():
If the current thread is the last thread to arrive, and a non-null barrier action was supplied in the constructor, then the current thread runs the action before allowing the other threads to continue. If an exception occurs during the barrier action then that exception will be propagated in the current thread and the barrier is placed in the broken state.
We have a scheduled task that runs every 10 seconds and a thread pool with 3 threads that actually update a static common map. Every 10 seconds the scheduled action prints this map.
The problem is that I want the scheduler to stop printing after the 3 threads finish with the map. But here is the key. I don't want to stop scheduler instantly, I want to print first ( the final version of the map) and then finishes.
public class myClass implements ThreadListener {
public static ArrayList<Pair<String, Integer>> wordOccurenceSet = new ArrayList<Pair<String, Integer>>();
int numberOfThreads = 0;
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
public void getAnswer(Collection<CharacterReader> characterReaders, Outputter outputter) {
ExecutorService executor = Executors.newFixedThreadPool(characterReaders.size());
OutputterWriteBatch scheduledThread = new OutputterWriteBatch(outputter,wordOccurenceSet);
scheduler.scheduleAtFixedRate(scheduledThread, 10, 10, TimeUnit.SECONDS);
for (CharacterReader characterReader : characterReaders) {
NotifyingRunnable runnable = new CharacterReaderTask(characterReader, wordOccurenceSet);
runnable.addListener(this);
executor.execute(runnable);
}
}
#Override
public void notifyRunnableComplete(Runnable runnable) {
numberOfThreads += 1;
if(numberOfThreads == 3 ){
//All threads finished... What can I do to terminate after one more run?
}
}
}
The Listener actually just get notified when a thread finishes.
First of all, make your numberOfThreads synchronized. You don't want it to become corrupted when two Reader threads finish concurrently. It's a primitive int so it may not be corruptable (i am not that proficient with JVM), but the general rules of thread safety should be followed anyway.
// 1. let finish OutputterWriteBatch if currently running
scheduler.shutdown();
// 2. will block and wait if OutputterWriteBatch was currently running
scheduler.awaitTermination(someReasonableTimeout);
// 3. one more shot.
scheduler.schedule(scheduledThread,0);
// You could also run it directly if your outputting logic in run()
// is published via separate method, but i don't know the API so i suppose
// only Runnable is published
But this shouldn't be called directly from notifyRunnableComplete, of course. The listener method is called from your Reader threads, so it would block the last one of 3 threads from finishing timely. Rather make a notification object which some other thread will wait() on (preferably the one which executed getAnswer()), notify() it when numberOfThreads reaches 3 and put the above code after the wait().
Oh, and when wait() unblocks, you should double check that numberOfThreads is really 3, if not, cycle back to wait(). Google "spurious wakeup" to explanation why this is needed.