I'm writing a listener thread for a server, and at the moment I'm using:
while (true){
try {
if (condition){
//do something
condition=false;
}
sleep(1000);
} catch (InterruptedException ex){
Logger.getLogger(server.class.getName()).log(Level.SEVERE, null, ex);
}
}
With the code above, I'm running into issues with the run function eating all the cpu time looping. The sleep function works, but it seems be a makeshift fix, not a solution.
Is there some function which would block until the variable 'condition' became 'true'?
Or is continual looping the standard method of waiting until a variable's value changes?
Polling like this is definitely the least preferred solution.
I assume that you have another thread that will do something to make the condition true. There are several ways to synchronize threads. The easiest one in your case would be a notification via an Object:
Main thread:
synchronized(syncObject) {
try {
// Calling wait() will block this thread until another thread
// calls notify() on the object.
syncObject.wait();
} catch (InterruptedException e) {
// Happens if someone interrupts your thread.
}
}
Other thread:
// Do something
// If the condition is true, do the following:
synchronized(syncObject) {
syncObject.notify();
}
syncObject itself can be a simple Object.
There are many other ways of inter-thread communication, but which one to use depends on what precisely you're doing.
EboMike's answer and Toby's answer are both on the right track, but they both contain a fatal flaw. The flaw is called lost notification.
The problem is, if a thread calls foo.notify(), it will not do anything at all unless some other thread is already sleeping in a foo.wait() call. The object, foo, does not remember that it was notified.
There's a reason why you aren't allowed to call foo.wait() or foo.notify() unless the thread is synchronized on foo. It's because the only way to avoid lost notification is to protect the condition with a mutex. When it's done right, it looks like this:
Consumer thread:
try {
synchronized(foo) {
while(! conditionIsTrue()) {
foo.wait();
}
doSomethingThatRequiresConditionToBeTrue();
}
} catch (InterruptedException e) {
handleInterruption();
}
Producer thread:
synchronized(foo) {
doSomethingThatMakesConditionTrue();
foo.notify();
}
The code that changes the condition and the code that checks the condition is all synchronized on the same object, and the consumer thread explicitly tests the condition before it waits. There is no way for the consumer to miss the notification and end up stuck forever in a wait() call when the condition is already true.
Also note that the wait() is in a loop. That's because, in the general case, by the time the consumer re-acquires the foo lock and wakes up, some other thread might have made the condition false again. Even if that's not possible in your program, what is possible, in some operating systems, is for foo.wait() to return even when foo.notify() has not been called. That's called a spurious wakeup, and it is allowed to happen because it makes wait/notify easier to implement on certain operating systems.
As nobody published a solution with CountDownLatch. What about:
public class Lockeable {
private final CountDownLatch countDownLatch = new CountDownLatch(1);
public void doAfterEvent(){
countDownLatch.await();
doSomething();
}
public void reportDetonatingEvent(){
countDownLatch.countDown();
}
}
Similar to EboMike's answer you can use a mechanism similar to wait/notify/notifyAll but geared up for using a Lock.
For example,
public void doSomething() throws InterruptedException {
lock.lock();
try {
condition.await(); // releases lock and waits until doSomethingElse is called
} finally {
lock.unlock();
}
}
public void doSomethingElse() {
lock.lock();
try {
condition.signal();
} finally {
lock.unlock();
}
}
Where you'll wait for some condition which is notified by another thread (in this case calling doSomethingElse), at that point, the first thread will continue...
Using Locks over intrinsic synchronisation has lots of advantages but I just prefer having an explicit Condition object to represent the condition (you can have more than one which is a nice touch for things like producer-consumer).
Also, I can't help but notice how you deal with the interrupted exception in your example. You probably shouldn't consume the exception like this, instead reset the interrupt status flag using Thread.currentThread().interrupt.
This because if the exception is thrown, the interrupt status flag will have been reset (it's saying "I no longer remember being interrupted, I won't be able to tell anyone else that I have been if they ask") and another process may rely on this question. The example being that something else has implemented an interruption policy based on this... phew. A further example might be that your interruption policy, rather that while(true) might have been implemented as while(!Thread.currentThread().isInterrupted() (which will also make your code be more... socially considerate).
So, in summary, using Condition is rougly equivalent to using wait/notify/notifyAll when you want to use a Lock, logging is evil and swallowing InterruptedException is naughty ;)
You could use a semaphore.
While the condition is not met, another thread acquires the semaphore.
Your thread would try to acquire it with acquireUninterruptibly()
or tryAcquire(int permits, long timeout, TimeUnit unit) and would be blocked.
When the condition is met, the semaphore is also released and your thread would acquire it.
You could also try using a SynchronousQueue or a CountDownLatch.
Lock-free solution(?)
I had the same issue, but I wanted a solution that didn't use locks.
Problem: I have at most one thread consuming from a queue. Multiple producer threads are constantly inserting into the queue and need to notify the consumer if it's waiting. The queue is lock-free so using locks for notification causes unnecessary blocking in producer threads. Each producer thread needs to acquire the lock before it can notify the waiting consumer. I believe I came up with a lock-free solution using LockSupport and AtomicReferenceFieldUpdater. If a lock-free barrier exists within the JDK, I couldn't find it. Both CyclicBarrier and CoundDownLatch use locks internally from what I could find.
This is my slightly abbreviated code. Just to be clear, this code will only allow one thread to wait at a time. It could be modified to allow for multiple awaiters/consumers by using some type of atomic collection to store multiple owner (a ConcurrentMap may work).
I have used this code and it seems to work. I have not tested it extensively. I suggest you read the documentation for LockSupport before use.
/* I release this code into the public domain.
* http://unlicense.org/UNLICENSE
*/
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
import java.util.concurrent.locks.LockSupport;
/**
* A simple barrier for awaiting a signal.
* Only one thread at a time may await the signal.
*/
public class SignalBarrier {
/**
* The Thread that is currently awaiting the signal.
* !!! Don't call this directly !!!
*/
#SuppressWarnings("unused")
private volatile Thread _owner;
/** Used to update the owner atomically */
private static final AtomicReferenceFieldUpdater<SignalBarrier, Thread> ownerAccess =
AtomicReferenceFieldUpdater.newUpdater(SignalBarrier.class, Thread.class, "_owner");
/** Create a new SignalBarrier without an owner. */
public SignalBarrier() {
_owner = null;
}
/**
* Signal the owner that the barrier is ready.
* This has no effect if the SignalBarrer is unowned.
*/
public void signal() {
// Remove the current owner of this barrier.
Thread t = ownerAccess.getAndSet(this, null);
// If the owner wasn't null, unpark it.
if (t != null) {
LockSupport.unpark(t);
}
}
/**
* Claim the SignalBarrier and block until signaled.
*
* #throws IllegalStateException If the SignalBarrier already has an owner.
* #throws InterruptedException If the thread is interrupted while waiting.
*/
public void await() throws InterruptedException {
// Get the thread that would like to await the signal.
Thread t = Thread.currentThread();
// If a thread is attempting to await, the current owner should be null.
if (!ownerAccess.compareAndSet(this, null, t)) {
throw new IllegalStateException("A second thread tried to acquire a signal barrier that is already owned.");
}
// The current thread has taken ownership of this barrier.
// Park the current thread until the signal. Record this
// signal barrier as the 'blocker'.
LockSupport.park(this);
// If a thread has called #signal() the owner should already be null.
// However the documentation for LockSupport.unpark makes it clear that
// threads can wake up for absolutely no reason. Do a compare and set
// to make sure we don't wipe out a new owner, keeping in mind that only
// thread should be awaiting at any given moment!
ownerAccess.compareAndSet(this, t, null);
// Check to see if we've been unparked because of a thread interrupt.
if (t.isInterrupted())
throw new InterruptedException();
}
/**
* Claim the SignalBarrier and block until signaled or the timeout expires.
*
* #throws IllegalStateException If the SignalBarrier already has an owner.
* #throws InterruptedException If the thread is interrupted while waiting.
*
* #param timeout The timeout duration in nanoseconds.
* #return The timeout minus the number of nanoseconds that passed while waiting.
*/
public long awaitNanos(long timeout) throws InterruptedException {
if (timeout <= 0)
return 0;
// Get the thread that would like to await the signal.
Thread t = Thread.currentThread();
// If a thread is attempting to await, the current owner should be null.
if (!ownerAccess.compareAndSet(this, null, t)) {
throw new IllegalStateException("A second thread tried to acquire a signal barrier is already owned.");
}
// The current thread owns this barrier.
// Park the current thread until the signal. Record this
// signal barrier as the 'blocker'.
// Time the park.
long start = System.nanoTime();
LockSupport.parkNanos(this, timeout);
ownerAccess.compareAndSet(this, t, null);
long stop = System.nanoTime();
// Check to see if we've been unparked because of a thread interrupt.
if (t.isInterrupted())
throw new InterruptedException();
// Return the number of nanoseconds left in the timeout after what we
// just waited.
return Math.max(timeout - stop + start, 0L);
}
}
To give a vague example of usage, I'll adopt james large's example:
SignalBarrier barrier = new SignalBarrier();
Consumer thread (singular, not plural!):
try {
while(!conditionIsTrue()) {
barrier.await();
}
doSomethingThatRequiresConditionToBeTrue();
} catch (InterruptedException e) {
handleInterruption();
}
Producer thread(s):
doSomethingThatMakesConditionTrue();
barrier.signal();
One could also leverage CompletableFutures (since Java 8):
final CompletableFuture<String> question = new CompletableFuture<>();
// from within the consumer thread:
final String answer = question.get(); // or: event.get(7500000, TimeUnit.YEARS)
// from within the producer thread:
question.complete("42");
Related
I am using multi-threading in java for my program.
I have run thread successfully but when I am using Thread.wait(), it is throwing java.lang.IllegalMonitorStateException.
How can I make a thread wait until it will be notified?
You need to be in a synchronized block in order for Object.wait() to work.
Also, I recommend looking at the concurrency packages instead of the old school threading packages. They are safer and way easier to work with.
EDIT
I assumed you meant Object.wait() as your exception is what happens when you try to gain access without holding the objects lock.
wait is defined in Object, and not it Thread. The monitor on Thread is a little unpredictable.
Although all Java objects have monitors, it is generally better to have a dedicated lock:
private final Object lock = new Object();
You can get slightly easier to read diagnostics, at a small memory cost (about 2K per process) by using a named class:
private static final class Lock { }
private final Object lock = new Lock();
In order to wait or notify/notifyAll an object, you need to be holding the lock with the synchronized statement. Also, you will need a while loop to check for the wakeup condition (find a good text on threading to explain why).
synchronized (lock) {
while (!isWakeupNeeded()) {
lock.wait();
}
}
To notify:
synchronized (lock) {
makeWakeupNeeded();
lock.notifyAll();
}
It is well worth getting to understand both Java language and java.util.concurrent.locks locks (and java.util.concurrent.atomic) when getting into multithreading. But use java.util.concurrent data structures whenever you can.
I know this thread is almost 2 years old but still need to close this since I also came to this Q/A session with same issue...
Please read this definition of illegalMonitorException again and again...
IllegalMonitorException is thrown to indicate that a thread has attempted to wait on an object's monitor or to notify other threads waiting on an object's monitor without owning the specified monitor.
This line again and again says, IllegalMonitorException comes when one of the 2 situation occurs....
1> wait on an object's monitor without owning the specified monitor.
2> notify other threads waiting on an object's monitor without owning the specified monitor.
Some might have got their answers... who all doesn't, then please check 2 statements....
synchronized (object)
object.wait()
If both object are same... then no illegalMonitorException can come.
Now again read the IllegalMonitorException definition and you wont forget it again...
Based on your comments it sounds like you are doing something like this:
Thread thread = new Thread(new Runnable(){
public void run() { // do stuff }});
thread.start();
...
thread.wait();
There are three problems.
As others have said, obj.wait() can only be called if the current thread holds the primitive lock / mutex for obj. If the current thread does not hold the lock, you get the exception you are seeing.
The thread.wait() call does not do what you seem to be expecting it to do. Specifically, thread.wait() does not cause the nominated thread to wait. Rather it causes the current thread to wait until some other thread calls thread.notify() or thread.notifyAll().
There is actually no safe way to force a Thread instance to pause if it doesn't want to. (The nearest that Java has to this is the deprecated Thread.suspend() method, but that method is inherently unsafe, as is explained in the Javadoc.)
If you want the newly started Thread to pause, the best way to do it is to create a CountdownLatch instance and have the thread call await() on the latch to pause itself. The main thread would then call countDown() on the latch to let the paused thread continue.
Orthogonal to the previous points, using a Thread object as a lock / mutex may cause problems. For example, the javadoc for Thread::join says:
This implementation uses a loop of this.wait calls conditioned on this.isAlive. As a thread terminates the this.notifyAll method is invoked. It is recommended that applications not use wait, notify, or notifyAll on Thread instances.
Since you haven't posted code, we're kind of working in the dark. What are the details of the exception?
Are you calling Thread.wait() from within the thread, or outside it?
I ask this because according to the javadoc for IllegalMonitorStateException, it is:
Thrown to indicate that a thread has attempted to wait on an object's monitor or to notify other threads waiting on an object's monitor without owning the specified monitor.
To clarify this answer, this call to wait on a thread also throws IllegalMonitorStateException, despite being called from within a synchronized block:
private static final class Lock { }
private final Object lock = new Lock();
#Test
public void testRun() {
ThreadWorker worker = new ThreadWorker();
System.out.println ("Starting worker");
worker.start();
System.out.println ("Worker started - telling it to wait");
try {
synchronized (lock) {
worker.wait();
}
} catch (InterruptedException e1) {
String msg = "InterruptedException: [" + e1.getLocalizedMessage() + "]";
System.out.println (msg);
e1.printStackTrace();
System.out.flush();
}
System.out.println ("Worker done waiting, we're now waiting for it by joining");
try {
worker.join();
} catch (InterruptedException ex) { }
}
In order to deal with the IllegalMonitorStateException, you must verify that all invocations of the wait, notify and notifyAll methods are taking place only when the calling thread owns the appropriate monitor. The most simple solution is to enclose these calls inside synchronized blocks. The synchronization object that shall be invoked in the synchronized statement is the one whose monitor must be acquired.
Here is the simple example for to understand the concept of monitor
public class SimpleMonitorState {
public static void main(String args[]) throws InterruptedException {
SimpleMonitorState t = new SimpleMonitorState();
SimpleRunnable m = new SimpleRunnable(t);
Thread t1 = new Thread(m);
t1.start();
t.call();
}
public void call() throws InterruptedException {
synchronized (this) {
wait();
System.out.println("Single by Threads ");
}
}
}
class SimpleRunnable implements Runnable {
SimpleMonitorState t;
SimpleRunnable(SimpleMonitorState t) {
this.t = t;
}
#Override
public void run() {
try {
// Sleep
Thread.sleep(10000);
synchronized (this.t) {
this.t.notify();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Thread.wait() call make sense inside a code that synchronizes on Thread.class object. I don't think it's what you meant.
You ask
How can I make a thread wait until it will be notified?
You can make only your current thread wait. Any other thread can be only gently asked to wait, if it agree.
If you want to wait for some condition, you need a lock object - Thread.class object is a very bad choice - it is a singleton AFAIK so synchronizing on it (except for Thread static methods) is dangerous.
Details for synchronization and waiting are already explained by Tom Hawtin.
java.lang.IllegalMonitorStateException means you are trying to wait on object on which you are not synchronized - it's illegal to do so.
Not sure if this will help somebody else out or not but this was the key part to fix my problem in user "Tom Hawtin - tacklin"'s answer above:
synchronized (lock) {
makeWakeupNeeded();
lock.notifyAll();
}
Just the fact that the "lock" is passed as an argument in synchronized() and it is also used in "lock".notifyAll();
Once I made it in those 2 places I got it working
I received a IllegalMonitorStateException while trying to wake up a thread in / from a different class / thread. In java 8 you can use the lock features of the new Concurrency API instead of synchronized functions.
I was already storing objects for asynchronous websocket transactions in a WeakHashMap. The solution in my case was to also store a lock object in a ConcurrentHashMap for synchronous replies. Note the condition.await (not .wait).
To handle the multi threading I used a Executors.newCachedThreadPool() to create a thread pool.
Those who are using Java 7.0 or below version can refer the code which I used here and it works.
public class WaitTest {
private final Lock lock = new ReentrantLock();
private final Condition condition = lock.newCondition();
public void waitHere(long waitTime) {
System.out.println("wait started...");
lock.lock();
try {
condition.await(waitTime, TimeUnit.SECONDS);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
lock.unlock();
System.out.println("wait ends here...");
}
public static void main(String[] args) {
//Your Code
new WaitTest().waitHere(10);
//Your Code
}
}
For calling wait()/notify() on object, it needs to be inside synchronized block. So first you have to take lock on object then would be possible to call these function.
synchronized(obj)
{
obj.wait()
}
For detailed explanation:
https://dzone.com/articles/multithreading-java-and-interviewspart-2
wait(), notify() and notifyAll() methods should only be called in syncronized contexts.
For example, in a syncronized block:
syncronized (obj) {
obj.wait();
}
Or, in a syncronized method:
syncronized static void myMethod() {
wait();
}
According to the basic definition of synchronized method from source - link
"When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object."
and I read about the wait() that it releases a lock before it sleeps. There is a confusion here if wait releases the lock then other thread can get-into the synchronized method and does it make sense because it may lead to race condition?
Here is my sample code that is allowing one and two thread into the synchronized block.
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
/**
*
* #author Ashish Pancholi
*/
public class Test {
public Test() {
Sharing sharing = new Sharing();
Worker worker_ = new Worker(sharing);
Thread thread_ = new Thread(worker_, "one");
Worker worker = new Worker(sharing);
Thread thread = new Thread(worker, "two");
thread_.start();
thread.start();
}
public static void main(String[] argu) {
Test test = new Test();
}
public class Worker implements Runnable {
private Sharing sharing;
public Worker(Sharing sharing) {
this.sharing = sharing;
}
#Override
public void run() {
sharing.check();
}
}
public class Sharing {
public void check() {
synchronized (this) {
System.out.println("Thread IN " + Thread.currentThread().getName());
try {
wait(5000);
} catch (InterruptedException ex) {
}
System.out.println("Thread OUT " + Thread.currentThread().getName());
}
}
}
}
Output-
Thread IN one
Thread IN two
Thread OUT one
Thread OUT two
Yes it makes sense.
The API of the wait() method says:
Causes the current thread to wait until either another thread invokes
the notify() method or the notifyAll() method for this object, or a
specified amount of time has elapsed.
So if the wait method would NOT release the lock on the monitor object, no other thread could get it and thus no other thread could invoke notify or notifyAll on that monitor object.
The wait(5000) means that the current thread will wait up to 5000 milliseconds for a notification before continuing or continue after 5000 ms. If you want to hold the lock and pause 5000 ms then you must use Thread.sleep(5000).
It makes sense that there might be race conditions. Race conditions naturally happen when dealing with multiple threads. It is your job to prevent them by carefully managing your threads, and the wait method is an important tool that you can use to help with that.
Normally you wouldn't simply call wait with a fixed 5-second pause like that. In a real application you would probably be waiting for some specific condition to be true, so your wait looks more like this:
try {
while(!condition) {
wait();
}
doSomething();
} catch(InterruptedException e) {
doSomethingElseWhenWeAreAskedNotToWait();
}
Whether you have a race condition depends upon when condition becomes true, who else might be waiting for that condition, and what everyone does when it happens. The reason wait gives up the lock is to give condition a chance to become true while we wait.
You are using synchronized with two different locks, so there is no synchronization happening between the two threads.
Synchronize on the instance of Test rather than Sharing, and the behaviour will be quite different.
I have a thread that updates it's state from time to time and I want a second thread to be able to wait for the first thread to be done. Something like this:
Thread 1:
while(true) {
...do something...
foo.notifyAll()
...wait for some condition that might never happen...
...
}
Thread 2:
...
foo.wait();
...
Now this looks nice and all unless Thread 1's notifyAll() runs before Thread 2's wait(), in which case Thread 2 waits until Thread 1 notifies again (which might never happen).
My possible solutions:
a) I could use a CountDownLatch or a Future, but both have the problem that they inherently only run once. That is, in Thread 1's while loop, I would need to create a new foo to wait for each time and Thread 2 would need to ask which foo to wait for. I have a bad feeling about simply writing
while(true) {
foo = new FutureTask();
...
foo.set(...);
...wait for a condition that might never be set...
...
}
as I fear that at foo = new FutureTask(), what happens when someone waited for the old foo (for "some reason", set was not called, e.g. a bug in the exception handling)?
b) Or I could use a semaphore:
class Event {
Semaphore sem;
Event() { sem = new Semaphore(1); sem . }
void signal() { sem.release(); }
void reset() { sem.acquire(1); }
void wait() { if (sem.tryAcquire(1)) { sem.release(); } }
}
But I fear that there is some race condition, if multiple threads are wait()ing for it while another one signal()s and reset()s.
Question:
Is there nothing in the Java API that resembles the Windows Event behaviour? Or, if you despise Windows, something like golang's WaitGroup (i.e. a CountDownLatch that allows countUp())? Anything?
How to do it manually:
Thread 2 cannot simply wait because of spurious wakeup and in Java there is no way to know why Object.wait() returned. So I need a condition variable that stores whether the event is signalled or not. Thread 2:
synchronized(foo) {
while(!condition) {
foo.wait();
}
}
And Thread 1 of course sets condition to true in a synchronized block. Thanks to weekens for the hint!
Is there an existing class that wraps that behaviour?
Or do I need to copy and paste the code all over?
It is standard practice to change some state when performing notifyAll and to check some state when performing wait().
e.g.
boolean ready = false;
// thread 1
synchronized(lock) {
ready = true;
lock.notifyAll();
}
// thread 2
synchronized(lock) {
while(!ready)
lock.wait();
}
With this approach, it doesn't matter if thread 1 or thread 2 acquires the lock first.
Some coding analysis tools will give you a warning if you use notify or wait without setting a value or checking a value.
You could use a wait() with timeout, in which case you are not risking to wait forever. Also note that wait() may return even if there was no notify() at all, so, you'll need to wrap your wait inside some conditioned loop. That's the standard way of waiting in Java.
synchronized(syncObject) {
while(condition.isTrue()) {
syncObject.wait(WAIT_TIMEOUT);
}
}
(in your Thread 2)
Edit: Moved synchronized outside the loop.
The simplest way is just to say
firstThread.join();
This will be blocking until the first thread is terminated.
But you can implement the same using wait/notify. Unfortunately you have not posted your real code fragments but I guess that if wait does not exit when you call notify it happens because you did not put both into synchronized block. Pay attention that the "argument" of synchronized block must be the same for wait/notify pair.
I'd use a BlockingQueue between the two threads. Using wait and notify is so 5 minutes ago ;)
enum Event {
Event,
Stop;
}
BlockingQueue<Event> queue = new LinkedBlockingQueue<Event>();
// Thread 1
try {
while(true) {
...do something...
queue.put(Event.Event);
...wait for some condition that might never happen...
...
}
} finally {
// Tell other thread we've finished.
queue.put(Event.Stop};
}
// Thread 2
...
switch ( queue.take() ) {
case Event:
...
break;
default:
...
break;
}
Seems there is only ugly solutions. I solve it using AtomicBoolean as flag and some sleep to prevent high cpu usage and timeout for unexpected lost event...
Here my code:
somewhere in thread class:
private static final int WAIT_DELAY_MS_HACK = 5000; //ms
private static final AtomicBoolean NeedToExecute = new AtomicBoolean(false);
In working thread, that need to send wake signal:
public static final void SendSignalToExecute(){
synchronized(NeedToExecute){
NeedToExecute.set(true);
NeedToExecute.notify();
}
}
In the thread that must wait signal:
//To prevent infinite delay when notify was already lost I use WAIT_DELAY_MS_HACK in wait().
//To prevent false interruption on unknown reason of JM I use while and check of AtomicBoolean by NeedToExecute.get() in it.
//To prevent high CPU usage in for unknown persistant interruption in wait I use additional sleep():
while (!NeedToExecute.get()){
synchronized(NeedToExecute){
try {
NeedToExecute.wait(WAIT_DELAY_MS_HACK); //if notify() was sent before we go into wait() but after check in while() it will lost forever... note that NeedToExecute.wait() releases the synchronized lock for other thread and re-acquires it before returning
} catch (InterruptedException ex) { //here also may be sleep or break and return
}
}
sleep(100); //if wait() will not wait - must be outside synchronized block or it may cause freeze thread with SendSignalToExecute()... :(
}
NeedToExecute.set(false); //revert back to reenter check in next iteration, but I use it for one waited thread it cycle "do ... wait" if you use multiple thread you need to synchronise somehow this revert
This snippet is from JCIP (Brian Goetz) listing 6.15
f.get() throws InterruptedException and ExecutionException. Now, these exceptions are specific to the future correct?
Meaning the specific task represented by the future was interrupted or had an internal exception.
Questions -
Why do I need to restore the interrupt using "Thread.currentThread().interrupt()"? , because isnt the interrupt flag for the thread my task ran in? This is a little confusing.
Why throw launderThrowable exception? If one of the downloadImage had an issue, shouldnt we just process the other downloaded images intead of throwing from here and thus just "not" processing the remaining futures?
package net.jcip.examples;
import java.util.*;
import java.util.concurrent.*;
import static net.jcip.examples.LaunderThrowable.launderThrowable;
/**
* Renderer
* <p/>
* Using CompletionService to render page elements as they become available
*
* #author Brian Goetz and Tim Peierls
*/
public abstract class Renderer {
private final ExecutorService executor;
Renderer(ExecutorService executor) {
this.executor = executor;
}
void renderPage(CharSequence source) {
final List<ImageInfo> info = scanForImageInfo(source);
CompletionService<ImageData> completionService =
new ExecutorCompletionService<ImageData>(executor);
for (final ImageInfo imageInfo : info)
completionService.submit(new Callable<ImageData>() {
public ImageData call() {
return imageInfo.downloadImage();
}
});
renderText(source);
try {
for (int t = 0, n = info.size(); t < n; t++) {
Future<ImageData> f = completionService.take();
ImageData imageData = f.get();
renderImage(imageData);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (ExecutionException e) {
throw launderThrowable(e.getCause());
}
}
interface ImageData {
}
interface ImageInfo {
ImageData downloadImage();
}
abstract void renderText(CharSequence s);
abstract List<ImageInfo> scanForImageInfo(CharSequence s);
abstract void renderImage(ImageData i);
}
When you catch InterruptedException interrupted flag gets reset and your thread is technically not interrupted anymore. However, you don't know if the code that called your code (or other code in the same thread), requires any additional interrupt handling. By calling interrupt() you raise the flag again and effectively saying to the rest of the application "This thread is still interrupted - act on it if necessary".
Consider example. You method is called from the loop that must terminate if thread is interrupted. You caught the exception and if you don't raise the flag, the loop will not terminate as required.
By catching InterruptedException, you are stopping the interruption from reaching the Thread in which you are running. But you want it to reach it, in case there is any special processing the Thread needs to do in case of interruption - you can't tell, so you'd better play it safe and allow it to percolate up. You may do some processing yourself (to clean up, exit what you are doing, etc), but you must pass it on. The best way to do this is to call Thread.currentThread().interrupt().
The interruption does not necessarily happen on the thread pool's thread. The interruption is for a point when your current thread is interrupted while you are waiting on the future's get to complete. For instance, if you made the Future accessible to another part of the program that can cancel the download, then Future.cancel(true) will cause that InterruptedException to occur which you can then clean up the rest of the data. And as Beohemaian mentioned, it is always safe to propogate the interruption.
Thats a good question. I think that was more of a design choice of what he wanted it to do. But you can easily hold onto that error and throw it after the rest complete. Something to think about though, what if its an OutOfMemoryError? Then the launder would be useful to only throw if its an Error and maybe not a RuntimeException.
Why invoke the method Thread.currentThread.interrupt() in the catch block?
This is done to keep state.
When you catch the InterruptedException and swallow it, you essentially prevent any higher-level methods/thread groups from noticing the interrupt. Which may cause problems.
By calling Thread.currentThread().interrupt(), you set the interrupt flag of the thread, so higher-level interrupt handlers will notice it and can handle it appropriately.
Java Concurrency in Practice discusses this in more detail in Chapter 7.1.3: Responding to Interruption. Its rule is:
Only code that implements a thread's interruption policy may swallow an interruption request. General-purpose task and library code should never swallow interruption requests.
I think this code sample makes things a bit clear.
The class which does the job :
public class InterruptedSleepingRunner implements Runnable {
#Override
public void run() {
doAPseudoHeavyWeightJob();
}
private void doAPseudoHeavyWeightJob() {
for (int i = 0; i < Integer.MAX_VALUE; i++) {
// You are kidding me
System.out.println(i + " " + i * 2);
// Let me sleep <evil grin>
if (Thread.currentThread().isInterrupted()) {
System.out.println("Thread interrupted\n Exiting...");
break;
} else {
sleepBabySleep();
}
}
}
protected void sleepBabySleep() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
The Main class:
public class InterruptedSleepingThreadMain {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(new InterruptedSleepingRunner());
thread.start();
// Giving 10 seconds to finish the job.
Thread.sleep(10000);
// Let me interrupt
thread.interrupt();
}
}
Try calling interrupt without setting the status back.
Note:
http://download.oracle.com/javase/7/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html
How do I stop a thread that waits for long periods (e.g., for input)?
For this technique to work, it's critical that any method that catches an interrupt exception and is not prepared to deal with it immediately reasserts the exception. We say reasserts rather than rethrows, because it is not always possible to rethrow the exception. If the method that catches the InterruptedException is not declared to throw this (checked) exception, then it should "reinterrupt itself" with the following incantation:
Thread.currentThread().interrupt();
This ensures that the Thread will reraise the InterruptedException as soon as it is able.
I would consider it a bad practice or at least a bit risky.
Usually higher level methods do not perform blocking operations and they will never see InterruptedException there. If you mask it in every place you perform interruptible operation, you will never get it.
The only rationale for Thread.currentThread.interrupt() and not raising any other exception or signaling interrupt request in any other way (e.g. setting interrupted local variable variable in a thread's main loop) is the situation where you really can't do anything with the exception, like in the finally blocks.
See Péter Török's answer, if you want to better understand implications of the Thread.currentThread.interrupt() call.
Refer from java doc
If this thread is blocked in an invocation of the wait(), join(),
sleep(long), then its interrupt status will be cleared and it will
receive an InterruptedException.
If this thread is blocked in an I/O operation, the thread's interrupt
status will be set, and the thread will receive a
ClosedByInterruptException.
If this thread is blocked in a Selector then the thread's interrupt
status will be set and it will return immediately from the selection
operation.
If none of the previous conditions hold then this thread's interrupt
status will be set.
So, if you change the sleepBabySleep() method in #Ajay George Answer to I/O operation or just a sysout, you don't have to set the status back to stop the program. (BTW, they don't even throw InterruptedException)
Just like #Péter Török said => This is done to keep state. (And particular for method that will throw InterruptedException)