I have a little problem. I've a Service which get a SingleTon Thread when onStartCommand() is triggered.
public int onStartCommand(Intent intent, int flags, int startId)
{
Thread t = myThreadFactory.getConnectionThreadWhatever();
if (t.isAlive() && !t.isinterrupted())
{
// do actions when thread is already alive
}
else
{
// do actions to start and run the thread. e.g. t = new ConnectionThread().start();
}
}
Now the Thread have a Runnable in a loop which is like (pseudocode!)
public static boolean isRunning = false;
public void run()
{
isRunning = true;
while (isRunning)
{
// open the httpconnection with a (read)timeout of 300 (long polling, whatever)
}
}
Now i=I would like to kill the Thread as soon as the connection drops in a Network Broadcast Receiver or whatever case.
What is the common way killing it instantly without waiting before the timeout (e.g. 300 seconds) occurred ?
Currently I am doing this in another class with
public void stopThreadconnectionInstantlyWhatever()
{
ConnectionThread.isRunning = false;
Thread t = myFactory.getConnectionThread();
t.interrupt();
}
Now the problem seems to be that the Thread may wait until the timout happen but every second is more battery usage which should be avoided. So.. any idea? :-)
Well, I could get the httpurlconnection with a singleton pattern aswell and kill it before the timeout appear, but this is just a case
Try to read this article
Implementing cancelable tasks Nothing in the language specification gives interruption any specific semantics, but in larger
programs, it is difficult to maintain any semantics for interruption
other than cancellation. Depending on the activity, a user could
request cancellation through a GUI or through a network mechanism such
as JMX or Web Services. It could also be requested by program logic.
For example, a Web crawler might automatically shut itself down if it
detects that the disk is full, or a parallel algorithm might start
multiple threads to search different regions of the solution space and
cancel them once one of them finds a solution. Just because a task is
cancelable does not mean it needs to respond to an interrupt request
immediately. For tasks that execute code in a loop, it is common to
check for interruption only once per loop iteration. Depending on how
long the loop takes to execute, it could take some time before the
task code notices the thread has been interrupted (either by polling
the interrupted status with Thread.isInterrupted() or by calling a
blocking method). If the task needs to be more responsive, it can poll
the interrupted status more frequently. Blocking methods usually poll
the interrupted status immediately on entry, throwing
InterruptedException if it is set to improve responsiveness. The one
time it is acceptable to swallow an interrupt is when you know the
thread is about to exit. This scenario only occurs when the class
calling the interruptible method is part of a Thread, not a Runnable
or general-purpose library code, as illustrated in Listing 5. It
creates a thread that enumerates prime numbers until it is interrupted
and allows the thread to exit upon interruption. The prime-seeking
loop checks for interruption in two places: once by polling the
isInterrupted() method in the header of the while loop and once when
it calls the blocking BlockingQueue.put() method.
public class PrimeProducer extends Thread {
private final BlockingQueue<BigInteger> queue;
PrimeProducer(BlockingQueue<BigInteger> queue) {
this.queue = queue;
}
public void run() {
try {
BigInteger p = BigInteger.ONE;
while (!Thread.currentThread().isInterrupted())
queue.put(p = p.nextProbablePrime());
} catch (InterruptedException consumed) {
/* Allow thread to exit */
}
}
public void cancel() { interrupt(); }}
Related
I've got pretty complex method, with few loops and other method calls. I'd like to make it possible to interrupt this method. The only solution I've found to do so, is by checking if Thread.currentThread().isInterrupted(). The problem is I'd like to check it in every iteration of every loop and in few other places. After doing that the code does not really look so nice.
So there are two questions really.
1. Is there any other way to stop the method when thread was interrupted than checking the same flag over and over again?
2. Is it better - mostly in case of performance - to just add !Thread.currentThread().isInterrupted() condition in every loop or use some method like the one below?
void checkIfInterrupted() {
if (Thread.interrupted()) {
throw new InterruptedException();
}
}
Preferred way is to check Thread.currentThread().isInterrupted() every loop in your thread. Viz. Java Concurrency In Practice - Listening 7.5:
class PrimeProducer extends Thread {
private final BlockingQueue<BigInteger> queue;
PrimeProducer(BlockingQueue<BigInteger> queue) {
this.queue = queue;
}
public void run() {
try {
BigInteger p = BigInteger.ONE;
while (!Thread.currentThread().isInterrupted())
queue.put(p = p.nextProbablePrime());
} catch (InterruptedException consumed) {
/* Allow thread to exit */
}
}
public void cancel() { interrupt(); }
}
There are two points in each loop iteration where interruption may be
detected: in the blocking put call, and by explicitly polling the
interrupted status in the loop header. The explicit test is not
strictly necessary here because of the blocking put call, but it makes
PrimeProducer more responsive to interruption because it checks for
interruption before starting the lengthy task of searching for a
prime, rather than after. When calls to interruptible blocking methods
are not frequent enough to deliver the desired responsiveness,
explicitly testing the interrupted status can help.
I was surprised to find Java concurrency timeouts do not stop blocked socket read operation in the thread.
I was using Selenium RemoteWebDriver to simulate a load test scenario. I have wrapped the execution of Selenium commands in a Callable and used get() method with the timeout parameter. It works perfectly when there are less than 3 concurrent threads executing but the situation deteriorates when there are 4 or more concurrent threads. Some of the threads get stuck at socket read and are stuck for longer than the timeout setting on the Callable.
I did some research online, the root cause was a hard-coded socket timeout of 3 hours in Selenium code. There used to be a hack to overwrite the setting using reflection but with the latest version I don't think it's hackable any more.
I wonder whether there is a way to stop the thread that is IO blocked externally since I don't want to change Selenium code and end up having to maintain my own version of Selenium.
Here's how I handle the thread timeout in my code:
ExecutorService executorService = Executors.newSingleThreadExecutor();
Future<Long> future = null;
try {
future = executorService.submit(new Callable<Long>() {
#Override
public Long call() throws Exception {
return commandProcessor.process(row);
}
});
timeTaken = future.get(currentTimeout, TimeUnit.MILLISECONDS);
executorService.shutdown();
} catch (Exception e) {
log.error(e.getMessage(), e);
// cancel the task
if (future != null && !future.isDone()) {
future.cancel(true);
}
executorService.shutdownNow();
}
And since it fails to timeout randomly, I even created another daemon thread to monitor this thread and shut it down from the outside, but it still fails to terminate the thread when socket read blocks.
In the try block:
TimeoutDaemon timeoutDaemon = new TimeoutDaemon(future, executorService, timeStarted);
// put a daemon on the main execution thread so it behaves
ExecutorService daemonExecutorService = Executors.newSingleThreadExecutor();
daemonExecutorService.submit(timeoutDaemon);
The TimeoutDaemon class:
private class TimeoutDaemon implements Runnable {
private Future<?> future;
private long timeStarted;
private ExecutorService taskExecutorService;
private TimeoutDaemon(Future<?> future, ExecutorService taskExecutorService, long timeStarted) {
this.future = future;
this.timeStarted = timeStarted;
this.taskExecutorService = taskExecutorService;
}
#Override
public void run() {
boolean running = true;
while (running) {
long currentTime = System.currentTimeMillis();
if (currentTime - timeStarted > currentTimeout + 1000) {
running = false;
if (!future.isDone()) {
String message = "Command execution is taking longer (%d ms) than the current timeout setting %d. Canceling the execution.";
message = String.format(message, currentTime - timeStarted, currentTimeout);
taskExecutorService.shutdownNow();
}
} else {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
log.error("Timeout Daemon interrupted. Test may be stuck. Close stuck browser windows if any.", e);
}
}
}
}
}
The only way I know of, is to close the sockets.
You're right it's disappointing that the api doesn't allow interrupt or something.
see also Interrupt/stop thread with socket I/O blocking operation
From the API spec:
List shutdownNow()
Attempts to stop all actively executing tasks, halts the processing of waiting tasks, and returns a list of the tasks that were awaiting execution.
This method does not wait for actively executing tasks to terminate. Use awaitTermination to do that.
There are no guarantees beyond best-effort attempts to stop processing actively executing tasks. For example, typical implementations will cancel via Thread.interrupt(), so any task that fails to respond to interrupts may never terminate.
You cannot interrupt Socket.read() operation.
You can take a look at the NIO package which offers InterruptibleChannel. It is possible to interrupt read and write operations on InterruptibleChannel by invoking its close method.
From the API:
If a thread is blocked in an I/O operation on an interruptible channel then another thread may invoke the channel's close method. This will cause the blocked thread to receive an AsynchronousCloseException.
If my thread receives an InterruptedException in a sleep(), how can I tell whether it was caused by a call on its .interrupt() or .notify() method?
The long story:
I have a View() class running in a thread. It should run worker(s) and update the view from time to time. It should also measure the time the worker took. The View() should be interruptable by the application (upon shutdown). The workers should wake up (notify) the thread during sleep when they have finished to measure the time they took. (Without notification, time measured would be rounded up to the next full sleep cycle which isn’t desired.) So an InterruptedException can be triggered by a call on the thread’s .interrupt() or .notify() method. How do I distinguish this inside the catch block?
public class View() implements Runnable {
Long started = null;
Long finished = null;
#Overload
public void run(){
Set<Thread> workers = new HashSet<Thread>();
for(int i = 1; i <= 5; i++){
Thread worker = new Thread(new Worker());
worker.start();
workers.add(worker);
}
started = System.getCurrentTimeMillis();
do{
try{
TimeUnit.SECONDS.sleep(3);
updateView();
}catch(InterruptedException e){
if(--> thread_was_notified <--){
finished = System.getCurrentTimeMillis();
updateView();
}
if(--> thread_was_notified <--){
for(Thread worker : workers)
worker.interrupt();
}
return;
}
}while(true);
}
protected void updateView(){
// …
}
}
I first guessed that InterruptedException would have Subclasses, but there are none directly known subclasses listet in the javadoc. Thread provides .isInterrupted(), but as said here: “By convention, any method that exits by throwing an InterruptedException clears interrupt status when it does so.” So I can’t tell from .isInterrupted() either. What’s the clean way to do it?
I have a vegue idea that my code should use Object.wait(), but what’s the waiting object?
The ugly solution:
Instead of having your Workers interrupting the View thread, put a method like this:
public void workedFinished() {
interruptedByWorker = true; // View attribute.
viewThread.interrupt(); // Interrupt the view
}
Then, when you're on your catch, check for the interruptedByWorker boolean. If it is true, it was interrupted by a worker. Otherwise (make sure this is happens), it was interrupted by the shutdown.
The other solution
Instead of interrupting the thread in two different places (which I think it could be confusing an error-prone), you could do the following:
1) Schedule a Runnable to run every 3 seconds using a ScheduledExecutorService to update the view.
2) Have a CountdownLatch that is notified for each Worker that finishes. Please, notice that in your code, the first thread wakes up the View, meaning that the measured time will be only for that thread, it will not wait until the other threads finish.
InterruptedException is only thrown when some thread interrupts you and not thrown when comming out of wait().
So when you are in sleep() or wait() and some other thread decides to interrupt you then Exception will be thrown.
When a thread is in wait() state and notify() is called for it then it will again fetch the lock and resume its working without throwing any exception.
I've written following multi thread program. I want to cancel the all the thread if one of the thread sends back false as return. However though I'm canceling the thread by canceling individual task. Its not working. What changes I need to make inorder to cancel the thread?
I've written following multi thread program. I want to cancel the all the thread if one of the thread sends back false as return. However though I'm canceling the thread by canceling individual task. Its not working. What changes I need to make inorder to cancel the thread?
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Callable;
public class BeamWorkerThread implements Callable<Boolean> {
private List<BeamData> beamData;
private String threadId;
public BeamScallopingWorkerThread(
List<BeamData> beamData, String threadId) {
super();
this.beamData = beamData;
this.threadId = threadId;
}
#Override
public Boolean call() throws Exception {
Boolean result = true;
DataValidator validator = new DataValidator();
Iterator<BeamScallopingData> it = beamData.iterator();
BeamData data = null;
while(it.hasNext()){
data = it.next();
if(!validator.validateDensity(data.getBin_ll_lat(), data.getBin_ll_lon(), data.getBin_ur_lat(), data.getBin_ur_lon())){
result = false;
break;
}
}
return result;
}
}
ExecutorService threadPool = Executors.newFixedThreadPool(100);
List<Future<Boolean>> results = new ArrayList<Future<Boolean>>();
long count = 0;
final long RowLimt = 10000;
long threadCount = 1;
while ((beamData = csvReader.read(
BeamData.class, headers1, processors)) != null) {
if (count == 0) {
beamDataList = new ArrayList<BeamData>();
}
beamDataList.add(beamData);
count++;
if (count == RowLimt) {
results.add(threadPool
.submit(new BeamWorkerThread(
beamDataList, "thread:"
+ (threadCount++))));
count = 0;
}
}
results.add(threadPool.submit(new BeamWorkerThread(
beamDataList, "thread:" + (threadCount++))));
System.out.println("Number of threads" + threadCount);
for (Future<Boolean> fs : results)
try {
if(fs.get() == false){
System.out.println("Thread is false");
for(Future<Boolean> fs1 : results){
fs1.cancel(true);
}
}
} catch(CancellationException e){
} catch (InterruptedException e) {
} catch (ExecutionException e) {
} finally {
threadPool.shutdownNow();
}
}
My comments
Thanks all for your input I'm overwhelmed by the response. I do know that, well implemented thread takes an app to highs and mean time it a bad implementation brings the app to knees. I agree I'm having fancy idea but I don't have other option. I've a 10 million plus record hence I will have memory constraint and time constraint. I need to tackle both. Hence rather than swallowing whole data I'm breaking it into chunks and also if one data is invalid i don't want to waste time in processing remaining million data. I find #Mark Peters suggestion is an option. Made the changes accordingly I mean added flag to interrupt the task and I'm pretty confused how the future list works. what I understand is that looping through each field of future list starts once all the thread returns its value. In that case, there is no way to cancel all the task in half way from main list. I need to pass on the reference of object to each thread. and if one thread finds invalid data using the thread refernce call the cancel mathod of each thread to set the interrupt flag.
while(it.hasNext() && !cancelled) {
if(!validate){
// loop through each thread reference and call Cancel method
}
}
Whatever attempt you make to cancel all the remaining tasks, it will fail if your code is not carefully written to be interruptible. What that exactly entails is beyond just one StackOverflow answer. Some guidelines:
do not swallow InterruptedException. Make its occurrence break the task;
if your code does not spend much time within interruptible methods, you must insert explicit Thread.interrupted() checks and react appropriately.
Writing interruptible code is in general not beginner's stuff, so take care.
Cancelling the Future will not interrupt running code. It primarily serves to prevent the task from being run in the first place.
While you can provide a true as a parameter, which will interrupt the thread running the task, that only has an effect if the thread is blocked in code that throws an InterruptedException. Other than that, nothing implicitly checks the interrupted status of the thread.
In your case, there is no blocking; it's busy work that is taking time. One option would be to have a volatile boolean that you check at each stage of your loop:
public class BeamWorkerThread implements Callable<Boolean> {
private volatile boolean cancelled = false;
#Override
public Boolean call() throws Exception {
//...
while(it.hasNext() && !cancelled) {
//...
}
}
public void cancel() {
cancelled = true;
}
}
Then you would keep references to your BeamWorkerThread objects and call cancel() on it to preempt its execution.
Why don't I like interrupts?
Marko mentioned that the cancelled flag above is essentially reinventing Thread.interrupted(). It's a valid criticism. Here's why I prefer not to use interrupts in this scenario.
1. It's dependent on certain threading configurations.
If your task represents a cancellable piece of code that can be submitted to an executor, or called directly, using Thread.interrupt() to cancel execution in the general case assumes that the code receiving the interrupt will be the code that should know how to cleanly cancel the task.
That might be true in this case, but we only know so because we know how both the cancel and the task work internally. But imagine we had something like this:
Task does piece of work
Listeners are notified on-thread for that first piece of work
First listener decides to cancel the task using Thread.interrupt()
Second listener does some interruptible piece of work, and is interrupted. It logs but otherwise ignores the interrupt.
Task does not receive interrupt, and task is not cancelled.
In other words, I feel that interrupt() is too global of a mechanism. Like any shared global state, it makes assumptions about all of the actors. That's what I mean by saying that using interrupt() exposes/couples to details about the run context. By encapsulating it in a cancel() method applicable only for that task instance, you eliminate that global state.
2. It's not always an option.
The classic example here is an InputStream. If you have a task that blocks on reading from an InputStream, interrupt() will do nothing to unblock it. The only way to unblock it is to manually close the stream, and that's something best done in a cancel() method for the task itself. Having one way to cancel a task (e.g. Cancellable), regardless of its implementation, seems ideal to me.
Use the ExecutorService.shutdownNow() method. It will stop the executor from accepting more submissions and returns with the Future objects of the ongoing tasks that you can call cancel(true) on to interrupt the execution. Of course, you will have to discard this executor as it cannot be restarted.
The cancel() method may not terminate the execution immediately if the Thread is not waiting on a monitor (not blocked interruptibly), and also if you swallow the InterruptedException that will be raised in this case.
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");