How to wait x seconds or until a condition becomes true? The condition should be tested periodically while waiting. Currently I'm using this code, but there should be a short function.
for (int i = 10; i > 0 && !condition(); i--) {
Thread.sleep(1000);
}
Assuming you want what you asked for, as opposed to suggestions for redesigning your code, you should look at Awaitility.
For example, if you want to see if a file will be created within the next 10 seconds, you do something like:
await().atMost(10, SECONDS).until(() -> myFile.exists());
It's mainly aimed at testing, but does the specific requested trick of waiting for an arbitrary condition, specified by the caller, without explicit synchronization or sleep calls. If you don't want to use the library, just read the code to see the way it does things.
Which, in this case, comes down to a similar polling loop to the question, but with a Java 8 lambda passed in as an argument, instead of an inline condition.
I didn't find a solution in the JDK. I think this feature should be added to the JDK.
Here what I've implemented with a Functional Interface:
import java.util.concurrent.TimeoutException;
import java.util.function.BooleanSupplier;
public interface WaitUntilUtils {
static void waitUntil(BooleanSupplier condition, long timeoutms) throws TimeoutException{
long start = System.currentTimeMillis();
while (!condition.getAsBoolean()){
if (System.currentTimeMillis() - start > timeoutms ){
throw new TimeoutException(String.format("Condition not met within %s ms",timeoutms));
}
}
}
}
Have you thought about some classes from java.util.concurrent - for example a BlockingQueue?
You could use:
BlockingQueue<Boolean> conditionMet = new BlockingQueue<Boolean>;
conditionMet.poll(10,TimeUnit.SECONDS);
And then in the code that changes your condition do this:
conditionMet.put(true);
EDIT:
Another example form java.util.concurrent may be CountDownLatch:
CountDownLatch siteWasRenderedLatch = new CountDownLatch(1);
boolean siteWasRendered = siteWasRenderedLatch.await(10,TimeUnit.SECONDS);
This way you'll wait 10 seconds or until the latch reaches zero. To reach zero all you have to do is:
siteWasRenderedLatch.countDown();
This way you won't need to use locks which would be needed in Condition examples presented by #Adrian. I think it's just simpler and straight-forward.
And if you don't like the naming 'Latch' or 'Queue' you can always wrap it into your own class called i.e. LimitedTimeCondition:
public class LimitedTimeCondition
{
private CountDownLatch conditionMetLatch;
private Integer unitsCount;
private TimeUnit unit;
public LimitedTimeCondition(final Integer unitsCount, final TimeUnit unit)
{
conditionMetLatch = new CountDownLatch(1);
this.unitsCount = unitsCount;
this.unit = unit;
}
public boolean waitForConditionToBeMet()
{
try
{
return conditionMetLatch.await(unitsCount, unit);
}
catch (final InterruptedException e)
{
System.out.println("Someone has disturbed the condition awaiter.");
return false;
}
}
public void conditionWasMet()
{
conditionMetLatch.countDown();
}
}
And the usage would be:
LimitedTimeCondition siteRenderedCondition = new LimitedTimeCondition(10, TimeUnit.SECONDS);
//
...
//
if (siteRenderedCondition.waitForConditionToBeMet())
{
doStuff();
}
else
{
System.out.println("Site was not rendered properly");
}
//
...
// in condition checker/achiever:
if (siteWasRendered)
{
condition.conditionWasMet();
}
Have a look at Condition.
Conditions (also known as condition queues or condition variables)
provide a means for one thread to suspend execution (to "wait") until
notified by another thread that some state condition may now be true.
Because access to this shared state information occurs in different
threads, it must be protected, so a lock of some form is associated
with the condition. The key property that waiting for a condition
provides is that it atomically releases the associated lock and
suspends the current thread, just like Object.wait.
A Condition instance is intrinsically bound to a lock. To obtain a
Condition instance for a particular Lock instance use its
newCondition() method.
EDIT:
Related question Sleep and check until condition is true
Related question is there a 'block until condition becomes true' function in java?
You may want to use something like the code below (where secondsToWait holds the maximum number of seconds you want to wait to see if the condition() turns true. The varialbe isCondetionMet will contain true if the condition was found, or false if the code timed out waiting for the condition.
long endWaitTime = System.currentTimeMillis() + secondsToWait*1000;
boolean isConditionMet = false;
while (System.currentTimeMillis() < endWaitTime && !isConditionMet) {
isConditionMet = condition();
if (isConditionMet) {
break;
} else {
Thread.sleep(1000);
}
}
I'm using the following adaptation of the original question's solution:
public class Satisfied {
public static boolean inTime(Callable<Boolean> condition, int timeoutInSecs) {
int count;
try {
for (count = 1; count < timeoutInSecs * 20 && !condition.call(); count++)
Thread.sleep(50);
return (count < timeoutInSecs * 20);
} catch (Exception e) {
throw new AssertionError(e.getMessage());
}
}
}
When used in testing, it appears like this:
assertThat(Satisfied.inTime(() -> myCondition(), 5)).isTrue();
Using await Awaitility:
Awaitility.with().pollDelay(1000, TimeUnit.MILLISECONDS).await().until(() -> true);
Related
According to the JLS 17 specification section 17.3:
For example, in the following (broken) code fragment, assume that this.done is a non-volatile boolean field:
while (!this.done)
Thread.sleep(1000);
The compiler is free to read the field this.done just once, and reuse the cached value in each execution of the loop. This would mean that the loop would never terminate, even if another thread changed the value of this.done
I have tried to simulate this following example: 2 threads concurrently access the same boolean variable, the first thread using the shared boolean in while loop, and the second thread update the boolean value.
1.Code without Thread.sleep() inside the first thread:
public boolean done;
public void performTest() throws InterruptedException {
done = false;
new Thread(() -> {
System.out.println("Running Thread 1...");
int count = 0;
while (!done) {
count++;
}
System.out.println("Exiting thread...");
}).start();
Thread.sleep(100);
new Thread(() -> {
System.out.println("Thread 2 setting done to true");
done = true;
}).start();
}
-> This code would never terminated, because the done variable not declared as volatile
2.Now change the code to include Thread.sleep() inside while loop as mentioned in the JLS
public boolean done;
public void performTest() throws InterruptedException {
done = false;
new Thread(() -> {
System.out.println("Running Thread 1...");
int count = 0;
while (!done) {
count++;
try {
Thread.sleep(0);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Exiting thread...");
}).start();
Thread.sleep(100);
new Thread(() -> {
System.out.println("Thread 2 setting done to true");
done = true;
}).start();
}
-> Now it successfully exists in the first thread.
So i am confused between this example and the JLS mentioned. Not sure what i am missing here.
Note: i also noticed that Venkat's also mentioned this example in one of his videos, and there is a blog post that explained this behavior, and it looks like there is something related to JIT optimization. What is really concerned me here is that this example is not like what is described in the JLS.
The reason that the code is broken in your example is because the JVM is free to use a cached version of done so that your loop would never end. When you have 'Thread.sleep()' in there, it is unlikely to happen, but it is still a possiblity. That means, you write some code and test it and it works great. Then you change an environment, or change a JVM and suddenly it is broken.
This is a poor benchmark, but it gives an idea.
public class VolatileTest implements Runnable{
boolean done = false;
public void run(){
long count = 0;
long start = System.nanoTime();
long end = Integer.MAX_VALUE;
while(!done){
count++;
if(count == end){
break;
}
//try{ Thread.sleep(0); } catch (Exception e){ break;}
}
System.out.println( System.nanoTime() - start + " with " + count + " iterations");
}
public static void main(String[] args) throws Exception{
VolatileTest vt = new VolatileTest();
new Thread(vt).start();
Thread.sleep(500);
vt.done = true;
}
}
Now there are 3 cases. 1st as written without any sleep/volatile.
650503733 with 2147483647 iterations
It took 650ms to complete Integer.MAX_VALUE iterations. note sometimes this
finishes faster than the 500ms I wait.
2nd case, volatile done.
499923823 with 1091070867 iterations
Now it never completes before vt.done is set to true.
3rd case. non-volatile with Thread.sleep
499905166 with 3031374 iterations
With the volatile version is 300 times faster than the Thread.sleep version. The non-volatile version is more intermittent in how fast it is but it is the fastest. I suspect due to when the JIT decides to cache done it gets a speed boost so to speak.
I'm not sure how to verify when it decides to cache the done variable, but I think that why JMH is necessary for these types of micro benchmarks.
I am trying to test the multithreading performance with sync'ed object. However,
with 1 thread or with 16 threads the execution time is the same.
The rest of the code is here.
https://codeshare.io/5oJ6Ng
public void run() {
start = new Date().getTime();
System.out.println(start);
while (threadlist.size() < 9000) { //16 or more
// try{Thread.sleep(100);}catch (Exception f){}
Thread t = new Thread(new Runnable() {
public void run() {
while (add(1,3) < 1000000);
end = new Date().getTime();
System.out.println((end-start));
}
});
threadlist.add(t);
while( threadlist.iterator().hasNext()){
threadlist.iterator().next().start();
try{threadlist.iterator().next().join();}catch (Exception a){}
}
}
}
There are some issues with your code. First:
public void run() {
while (true) {
add(1, 3);
}
}
Those threads never stop working, I would suggest rewriting your logic to:
public void (run) {
while(add(1,3) < 1000000);
System.out.println("now 1000000");
}
public int add(int val1, int val2) {
synchronized (this) {
this.sum1 += val1;
this.sum2 += val2;
return this.sum1 + this.sum2;
}
}
}
You start the threads, but you never call join, eventually you will need to do that.
You are only creating 1 thread instead of the 16 that you wanted:
if (threadlist.size() < 1)
you want
if (threadlist.size() < 16)
Finally, do not expect any performance gain with this code, since you are synchronizing on the object:
synchronized (this){...}
So basically your add method is being run sequentially and not in parallel, since threads will wait on synchronized (this) and call only run on at the time inside your the block of code wrapped by the synchronized statement.
Try to measure your time by adding start = new Date().getTime(); before the parallel region, and end = new Date().getTime(); after.
You can simply your code to:
public void run() {
start = new Date().getTime();
System.out.println(start);
while (threadlist.size() < 16) {
Thread t = new Thread(() -> {
while (add(1,3) < 1);
System.out.println("now 1000000");
});
threadlist.add(t);
}
threadlist.forEach(Thread::start);
threadlist.forEach(thr-> {
try { thr.join();}
catch (InterruptedException e) { e.printStackTrace();}
});
end = new Date().getTime();
System.out.println("Time taken : "+(end-start));
public int add(int val1, int val2) {
synchronized (this) {
this.sum1 += val1;
this.sum2 += val2;
return this.sum1 + this.sum2;
}
}
}
You've significantly updated your code since #dreamcrash answered.
The current version has the following issues:
while( threadlist.iterator().hasNext()) {
threadlist.iterator().next().start();
try{threadlist.iterator().next().join();}catch (Exception a){}
}
This starts a thread and then will immediately sit around, twiddling its thumbs until that thread is completely done with its job, and will then fire up another thread. Therefore, you never more than 1 active thread at a time.
catch (Exception a){}
You're learning / debugging, and you do this? Oh dear. Don't. Don't ever write a catch block like that. Update your IDE or your muscle memory: The right "I dont want to think about exceptions right now" code is catch (Exception a) { throw new RuntimeException("Unhandled", a);}. To be clear, this isn't the problem, but this is such a bad habit, it needed to be called out.
synchronized (this) {
I really doubt if you fix the 'join' issue I mentioned earlier this will ever run any faster. This synchronized call is important, but it also causes so much blockage that you're likely to see zero actual benefit here.
More generally the calculation you are trying to speed up involves an accumulator.
accumulator is another word for 'parallelising is utterly impossible here, it is hopeless'.
The algorithm cannot involve accumulators if you want to parallellize it, which is what multithreading (at least, if the aim of the multiple threads is to speed things up) is doing. This algorithm cannot be made any faster with threads. period.
Usually algorithms can be rewritten to stop relying on accumulators. But this is clearly an exercise to see an effect, so, just find anything else, really. Don't lock on a single object for the entire calculation: Only one thread is ever actually doing work, all the 999 others are just waiting.
I am looking for mechanism which will help me to implement following pattern (pseudocode):
TimeoutLock lock = new TimeoutLock();
while(condition) {
prepare();
lock.enter(); //cannot enter until specified lock timeout elapses
execute();
lock.lockFor(2 minutes);
finish();
}
I need to limit invocations to execute to occur no more often, than some specified interval (for example, two minutes), but I do not want to block prepare or execute if it is not necessary. I am wondering if java supports any locking mechanism, which 'vanishes' after some time. Requirement is that, of course, lock does not pass through even if it's entered by the same thread, which locked it.
I was thinking about solution involving semaphore and TimerTask, or calculating deadline by myself and sleeping for superfluous time, but I wonder if something like this is already available.
Thanks
The below will do
basically you have a semphore which will only let you access if there is a permit available, I this case zero permits. So it will try for 2000 seconds before finally giving up
->
Semaphore s = new Semaphore(0);
Object lock = new Object();
synchronized(lock)
{
execute();
s.tryAcquire(2,TimeUnit.Minutes)
}
Thread.sleep is a lame and low level way of doing it. Not recommended
No need for a special class:
synchronized(lock) {
execute();
Thread.sleep(120 * 1000)
}
As Marko says, you very likely want to do this by handing the work off to a scheduler of some sort, rather than blocking the thread.
But if you do want to do this, i would suggest that you do it by recording a timestamp on exiting the critical section, and having entering threads wait for a period after that to pass. Something like:
public class TimeoutLock {
private boolean held;
private long available;
public void enter() throws InterruptedException {
acquire();
long pause;
while ((pause = available - System.currentTimeMillis()) > 0L) {
Thread.sleep(pause);
}
}
private synchronized void acquire() throws InterruptedException {
while (held) {
wait();
}
held = true;
}
public synchronized void lockFor(long period) {
held = false;
available = System.currentTimeMillis() + period;
notify();
}
}
You could use the sleep
sleep(1000);
I'm using the observer pattern and a BlockingQueue to add some instances. Now in another method I'm using the queue, but it seems take() is waiting forever, even though I'm doing it like this:
/** {#inheritDoc} */
#Override
public void diffListener(final EDiff paramDiff, final IStructuralItem paramNewNode,
final IStructuralItem paramOldNode, final DiffDepth paramDepth) {
final Diff diff =
new Diff(paramDiff, paramNewNode.getNodeKey(), paramOldNode.getNodeKey(), paramDepth);
mDiffs.add(diff);
try {
mDiffQueue.put(diff);
} catch (final InterruptedException e) {
LOGWRAPPER.error(e.getMessage(), e);
}
mEntries++;
if (mEntries == AFTER_COUNT_DIFFS) {
try {
mRunner.run(new PopulateDatabase(mDiffDatabase, mDiffs));
} catch (final Exception e) {
LOGWRAPPER.error(e.getMessage(), e);
}
mEntries = 0;
mDiffs = new LinkedList<>();
}
}
/** {#inheritDoc} */
#Override
public void diffDone() {
try {
mRunner.run(new PopulateDatabase(mDiffDatabase, mDiffs));
} catch (final Exception e) {
LOGWRAPPER.error(e.getMessage(), e);
}
mDone = true;
}
whereas mDiffQueue is a LinkedBlockingQueue and I'm using it like this:
while (!(mDiffQueue.isEmpty() && mDone) || mDiffQueue.take().getDiff() == EDiff.INSERTED) {}
But I think the first expression is checked whereas mDone isn't true, then maybe mDone is set to true (an observer always is multithreaded?), but it's already invoking mDiffQueue.take()? :-/
Edit: I really don't get it right now. I've recently changed it to:
synchronized (mDiffQueue) {
while (!(mDiffQueue.isEmpty() && mDone)) {
if (mDiffQueue.take().getDiff() != EDiff.INSERTED) {
break;
}
}
}
If I wait in the debugger a little time it works, but it should also work in "real time" since mDone is initialized to false and therefore the while-condition should be true and the body should be executed.
If the mDiffQueue is empty and mDone is true it should skip the body of the while-loop (which means the queue isn't filled anymore).
Edit: Seems it is:
synchronized (mDiffQueue) {
while (!(mDiffQueue.isEmpty() && mDone)) {
if (mDiffQueue.peek() != null) {
if (mDiffQueue.take().getDiff() != EDiff.INSERTED) {
break;
}
}
}
}
Even though I don't get why the peek() is mandatory.
Edit:
What I'm doing is iterating over a tree and I want to skip all INSERTED nodes:
for (final AbsAxis axis = new DescendantAxis(paramRtx, true); axis.hasNext(); axis.next()) {
skipInserts();
final IStructuralItem node = paramRtx.getStructuralNode();
if (node.hasFirstChild()) {
depth++;
skipInserts();
...
Basically computing the maximum depth or level in the tree without considering nodes which have been deleted in another revision of the tree (for a comparsion Sunburst visualization), but ok, that's maybe out of scope. Just to illustrate that I'm doing something with nodes which haven't been inserted, even if it's just adjusting the maximum depth.
regards,
Johannes
take() is a "blocking call". That means it will block (wait forever) until something is on the queue then it will return what was added. Of course, if something is on the queue, it will return immediately.
You can use peek() to return what would be returned by take() - that is, peek() returns the next item without removing it from the queue, or returns null if there's nothing on the queue. Try using peek() instead in your test (but check for null too).
First advice: don't synchronized (mDiffQueue). You would get deadlock if the LinkedBlockingQueue had some synchronized method; it's not the case here, but it's a practice that you should avoid. Anyway, I don't see why you are synchronizing at that point.
You have to "wake up" periodically while waiting to check if mDone has been set:
while (!(mDiffQueue.isEmpty() && mDone)) {
// poll returns null if nothing is added in the queue for 0.1 second.
Diff diff = mDiffQueue.poll(0.1, TimeUnit.SECONDS);
if (diff != null)
process(diff);
}
This is about the same as using peek, but peek basically waits for a nanosecond instead. Using peek is called "busy waiting" (your thread runs the while loop non-stop) and using pool is called "semi-busy waiting" (you let the thread sleep at intervals).
I guess in your case process(diff) would be to get out of the loop if diff is not of type EDiff.INSERTED. I'm not sure if that is what you are trying to accomplish. This seems odd since you are basically just stalling the consumer thread until you get a single element of the right type, and then you do nothing with it. And you cannot receive the future incoming elements since you are out of the while loop.
First, this is a near duplicate of:
How to differentiate when wait(long timeout) exit for notify or timeout?
But it is a new follow-on question.
Having this wait declaration:
public final native void wait(long timeout) throws InterruptedException;
It could exit by InterruptedException, or by timeout, or because Notify/NotifyAll method was called in another thread, Exception is easy to catch but...
My code absolutely needs to know if the exit was from timeout or notify. (In the future, this code needs to be redesigned, but that cannot be done now. So I need to know the reason for the exit from wait.)
Specifically, can someone give an example of using a ThreadLocal Boolean that is set to true only on notify() and where all this is inside an existing loop as shown below? (This was more or less the accepted answer in the other thread, but no specific code example was given. I'm not all that familiar with Java, so I need a specific code example -- ideally in the context of the existing code below.)
public synchronized int getLastSequenceNumber() {
while (empty) {
try {
wait(waitTimeValue);
} catch (InterruptedException e) {}
}
empty = true;
return reportedSequenceNumber;
}
public synchronized void reconcileLastSequenceNumber(int sequenceNumber) {
empty = false;
this.reportedSequenceNumber = sequenceNumber;
notifyAll();
}
the Boolean "empty" serves a purpose outside of the specific question I'm asking here. I believe I will need to add another Boolean to fulfill the suggested answer from the original question. How would I integrate that proposed solution into the existing code snippet above? Thanks.
You might be better off using a Condition (and its await method) rather than built-in monitors, because await returns a boolean value indicating whether the wait timed out.
And even then, you must beware of spurious wakeup (which is indistinguishable from a call to signal.)
You should be using a loop as you currently are anyway, regardless of knowing whether the wait timed out - partly due to the possibility of spurious wakeups. However, I'm not at all sure that you really need to know whether the call exited due to notification or not.
Consider the situation where the notification occurs a nanosecond before the timeout vs the situation where the notification occurs a nanosecond after the timeout. What's the useful difference between the two? Fundamentally there's a race condition if the two occur at "about the same time".
As far as I can tell, wait() really doesn't let you tell whether the call timed out or not, but it shouldn't affect your code. You should be looping and testing something else that is a side-effect of the notification anyway.
It's not clear to me where a ThreadLocal would come into play to be honest - that's exactly the opposite of what you want if you need to be able to tell from the waiting thread whether the notifying the thread has reached a certain point. I don't think you need an extra variable at all - your empty is fine.
There's no direct way to report this with the builtin monitor API, but you could replace the wait() and other functions with a new implementation that tracks this explicitly (untested):
private int wait_ct = 0, signal_ct = 0;
public void checkedNotifyAll() {
synchronized {
signal_ct = wait_ct;
notifyAll();
}
}
public void checkedNotify() {
synchronized {
signal_ct++;
if (signal_ct > wait_ct)
signal_ct = wait_ct;
notify();
}
// Returns true if awoken via notify
public boolean waitChecked(long timeout, int nanos) throws InterruptedException {
synchronized(this) {
try {
wait_ct++;
super.wait(timeout, nanos);
if (signal_ct > 0) {
signal_ct--;
return true;
}
return false;
} finally {
wait_ct--;
if (signal_ct > wait_ct) signal_ct = wait_ct;
notify(); // in case we picked up the notify but also were interrupted
}
}
// Note: Do not combine this with normal wait()s and notify()s; if they pick up the signal themselves
// the signal_ct will remain signalled even though the checkedWait()s haven't been
// awoken, potentially resulting in incorrect results in the event of a spurious wakeup
This isn't necessarily a good way to do this, of course; if you timeout just before notify() is called, the signal condition may be lost, after all. You really should be waiting in a loop, checking some persistent condition.
This is an expanded version based on Jenkov's signal class. An exception is raised if it does not end with a Notify. Thought it might help as I ran into the same problem.
public class MonitorObject{
}
public class Signal{
MonitorObject myMonitorObject = new MonitorObject();
boolean wasSignalled = false;
public void doWait(int timeOut) throws InterruptedException,TimeoutException{
synchronized(myMonitorObject){
long startTime = System.currentTimeMillis();
long endTime = startTime + timeOut;
Log.d(TAG, String.format("MonitorStart time %d",startTime));
while(!wasSignalled){
long waitTime = endTime - System.currentTimeMillis();
if(waitTime > 0)
myMonitorObject.wait(waitTime);
else{
Log.e(TAG, String.format("Monitor Exit timeout error"));
throw new TimeoutException();
}
}
Log.d(TAG, String.format("MonitorLoop Exit currentTime=%d EndTime=%d",System.currentTimeMillis(),startTime + timeOut));
//Spurious signal so clear signal and continue running.
wasSignalled = false;
}
}
public void doNotify(){
synchronized(myMonitorObject){
wasSignalled = true;
myMonitorObject.notify();
}
}
}