java - blockingQueue with condition Issue - java

I've two threads the first one execute some tasks (called TaskManager)
and the second listen to events and store them in a queue (called EventManager).
EventManager should be woken up and start running only if the queue is not empty and some condition is true.(when EventManager is not currently executing !eventManager.isRunning())
Ex. code:
class TaskManager implements Runnable {
#Override
public void run() {
try {
while (true) {
Object event = blockingQueue.take();
while(event != null && eventManager.isRunning()) {
}
// handle event
}
} catch (InterruptedException ie) {
// handle exception
} catch (Exception e) {
// handle exception
}
}
}
In this way the thread will be waiting as long as nothing is in the queue but will loop endlessly if the eventManager is still running which will cause starvation.
Is there any existing framework like blockingQueue that will wait and be woken when something is inserted to the queue
and another condition will meet(which keep Fairness).
I can solve that by using notify() & wait() myself but i prefer to use existing solutions.
Any suggestions will be appreciated?

Related

Interrupting unknown thread

Consider the following (simplified) class, designed to allow my entire component to enter some interim state before completely stopping. (The purpose of the interim state is to allow the component to complete its existing tasks, but reject any new ones).
The component might be started and stopped multiple times from any number of threads.
class StopHandler {
boolean isStarted = false;
synchronized void start() {isStarted = true;}
//synchronized as I do want the client code to block until the component is stopped.
//I might add some async method as well, but let's concentrate on the sync version only.
synchronized void stop(boolean isUrgent) {
if (isStarted) {
if (!isUrgent) {
setGlobalState(PREPARING_TO_STOP); //assume it is implemented
try {Thread.sleep(10_000L);} catch (InterruptedException ignored) {}
}
isStarted = false;
}
}
The problem with the current implementation is that if some client code needs to urgently stop the component while it is in the interim state, it will still have to wait.
For example:
//one thread
stopHandler.stop(false); //not urgent => it is sleeping
//another thread, after 1 millisecond:
stopHandler.stop(true); //it's urgent, "please stop now", but it will wait for 10 seconds
How would you implement it?
I might need to interrupt the sleeping thread, but I don't have the sleeping thread object on which to call 'interrupt()'.
How about storing a reference to current Thread (returned by Thread.currentThread()) in a field of StopHandler directly before you call sleep? That would allow you you to interrupt it in the subsequent urgent call in case the Thread is still alive.
Couldn't find a better solution than the one suggested by Lars.
Just need to encapsulate the sleep management for completeness.
class SleepHandler {
private final ReentrantLock sleepingThreadLock;
private volatile Thread sleepingThread;
SleepHandler() {
sleepingThreadLock = new ReentrantLock();
}
void sleep(long millis) throws InterruptedException {
setSleepingThread(Thread.currentThread());
Thread.sleep(millis);
setSleepingThread(null);
}
void interruptIfSleeping() {
doWithinSleepingThreadLock(() -> {
if (sleepingThread != null) {
sleepingThread.interrupt();
}
});
}
private void setSleepingThread(#Nullable Thread sleepingThread) {
doWithinSleepingThreadLock(() -> this.sleepingThread = sleepingThread);
}
private void doWithinSleepingThreadLock(Runnable runnable) {
sleepingThreadLock.lock();
try {
runnable.run();
} finally {
sleepingThreadLock.unlock();
}
}
}
With this helper class, handling of the original problem is trivial:
void stop(boolean isUrgent) throws InterruptedException {
if (isUrgent) {sleepHandler.interruptIfSleeping();} //harmless if not sleeping
try {
doStop(isUrgent); //all the stuff in the original 'stop(...)' method
} catch (InteruptedException ignored) {
} finally {
Thread.interrupted(); //just in case, clearing the 'interrupt' flag as no need to propagate it futher
}

Calling wait() after posting a runnable to UI thread until completion

I'm actually in need of waiting for the ui thread to execute a runnable before my application thread can continue. Is the wait()/notify() way a proper way to do it or is there something better for this? What I'm actually doing looks like this:
public void showVideoView() {
try {
final AtomicBoolean done = new AtomicBoolean(false);
final Runnable task = new Runnable() {
#Override
public void run() {
synchronized(this) {
mStartupCurtain.setVisibility(View.GONE);
mVideoView.setVisibility(View.VISIBLE);
mWebView.loadUrl("about:blank");
mWebView.setVisibility(View.GONE);
done.set(true);
notify();
}
}
};
mUiHandler.post(task);
synchronized(task) {
while(!done.get()) {
task.wait();
}
Log.d(TAG, "showVideoView done!");
}
} catch (InterruptedException e) {
Log.e(TAG, "Thread got interrupted while waiting for posted runnable to finish its task");
}
}
Also when I do this I have to be sure that the thread is not the one of the UI, which happens when I start calling methods from a listener method coming from an interface like MediaPlayer.OnCompletionListener.
What do you think?
Looks fine to me.
The "done" variable could be a regular Boolean instead of AtomicBoolean since you definitively get/set it's value within the lock. I like that you check the value of "done" prior to calling wait - since it is quite possible the task will have been completed before you ever enter the lock in the worker thread. If you had not done that, the wait() call would go indefinitely since the notify() had already happened.
There is one edge case to consider that may or may not be applicable to your design. What happens if the UI thread is attempting to exit (i.e. app exit) when the worker thread is still stuck waiting for the task to complete? Another variation is when the worker thread is waiting on the task to complete, but the UI thread is waiting on the worker thread to exit. The latter could be solved with another Boolean variable by which the UI thread signals the worker thread to exit. These issues may or may not be relevant - depending on how the UI is managing the thread to begin with.
Use AsyncTask!
AsyncTask enables proper and easy use of the UI thread. This class
allows to perform background operations and publish results on the UI
thread without having to manipulate threads and/or handlers.
http://developer.android.com/reference/android/os/AsyncTask.html
Function:
public static void postOnUI(Runnable runnable,boolean wait) {
if (Looper.getMainLooper().getThread() == Thread.currentThread()) {
// Is on UI thread.
runnable.run();
return;
}
Handler uiHandler = new Handler(Looper.getMainLooper());
AtomicBoolean done = new AtomicBoolean(false);
uiHandler.post(() -> {
runnable.run();
done.set(true);
});
if (wait) {
while (!done.get()) {
try {
Thread.sleep(20);
} catch (InterruptedException e) {
}
}
}
}
Usage Example:
Utils.postOnUI(headerView::updateUI,true);

Blocking queue and multi-threaded consumer, how to know when to stop

I have a single thread producer which creates some task objects which are then added into an ArrayBlockingQueue (which is of fixed size).
I also start a multi-threaded consumer. This is build as a fixed thread pool (Executors.newFixedThreadPool(threadCount);). I then submit some ConsumerWorker intances to this threadPool, each ConsumerWorker having a refference to the above mentioned ArrayBlockingQueue instance.
Each such Worker will do a take() on the queue and deal with the task.
My issue is, what's the best way to have a Worker know when there won't be any more work to be done. In other words, how do I tell the Workers that the producer has finished adding to the queue, and from this point on, each worker should stop when he sees that the Queue is empty.
What I've got now is a setup where my Producer is initialized with a callback which is triggered when he finishes it's job (of adding stuff to the queue). I also keep a list of all the ConsumerWorkers I've created and submitted to the ThreadPool. When the Producer Callback tells me that the producer is done, I can tell this to each of the workers. At this point they should simply keep checking if the queue is not empty, and when it becomes empty they should stop, thus allowing me to gracefully shutDown the ExecutorService thread pool. It's something like this
public class ConsumerWorker implements Runnable{
private BlockingQueue<Produced> inputQueue;
private volatile boolean isRunning = true;
public ConsumerWorker(BlockingQueue<Produced> inputQueue) {
this.inputQueue = inputQueue;
}
#Override
public void run() {
//worker loop keeps taking en element from the queue as long as the producer is still running or as
//long as the queue is not empty:
while(isRunning || !inputQueue.isEmpty()) {
System.out.println("Consumer "+Thread.currentThread().getName()+" START");
try {
Object queueElement = inputQueue.take();
//process queueElement
} catch (Exception e) {
e.printStackTrace();
}
}
}
//this is used to signal from the main thread that he producer has finished adding stuff to the queue
public void setRunning(boolean isRunning) {
this.isRunning = isRunning;
}
}
The problem here is that I have an obvious race condition where sometimes the producer will finish, signal it, and the ConsumerWorkers will stop BEFORE consuming everything in the queue.
My question is what's the best way to synchronize this so that it all works ok? Should I synchronize the whole part where it checks if the producer is running plus if the queue is empty plus take something from the queue in one block (on the queue object)? Should I just synchronize the update of the isRunning boolean on the ConsumerWorker instance? Any other suggestion?
UPDATE, HERE'S THE WORKING IMPLEMENTATION THAT I'VE ENDED UP USING:
public class ConsumerWorker implements Runnable{
private BlockingQueue<Produced> inputQueue;
private final static Produced POISON = new Produced(-1);
public ConsumerWorker(BlockingQueue<Produced> inputQueue) {
this.inputQueue = inputQueue;
}
#Override
public void run() {
//worker loop keeps taking en element from the queue as long as the producer is still running or as
//long as the queue is not empty:
while(true) {
System.out.println("Consumer "+Thread.currentThread().getName()+" START");
try {
Produced queueElement = inputQueue.take();
Thread.sleep(new Random().nextInt(100));
if(queueElement==POISON) {
break;
}
//process queueElement
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("Consumer "+Thread.currentThread().getName()+" END");
}
}
//this is used to signal from the main thread that he producer has finished adding stuff to the queue
public void stopRunning() {
try {
inputQueue.put(POISON);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
This was inspired heavily by JohnVint's answer below, with only some minor modifications.
=== Update due to #vendhan's comment.
Thank you for your obeservation. You are right, the first snippet of code in this question has (amongst other issues) the one where the while(isRunning || !inputQueue.isEmpty()) doesn't really make sense.
In my actual final implementation of this, I do something which is closer to your suggestion of replacing "||" (or) with "&&" (and), in the sense that each worker (consumer) now only checks if the element he's got from the list is a poison pill, and if so stops (so theoretically we can say that the worker has to be running AND the queue must not be empty).
You should continue to take() from the queue. You can use a poison pill to tell the worker to stop. For example:
private final Object POISON_PILL = new Object();
#Override
public void run() {
//worker loop keeps taking en element from the queue as long as the producer is still running or as
//long as the queue is not empty:
while(isRunning) {
System.out.println("Consumer "+Thread.currentThread().getName()+" START");
try {
Object queueElement = inputQueue.take();
if(queueElement == POISON_PILL) {
inputQueue.add(POISON_PILL);//notify other threads to stop
return;
}
//process queueElement
} catch (Exception e) {
e.printStackTrace();
}
}
}
//this is used to signal from the main thread that he producer has finished adding stuff to the queue
public void finish() {
//you can also clear here if you wanted
isRunning = false;
inputQueue.add(POISON_PILL);
}
I'd send the workers a special work packet to signal that they should shut down:
public class ConsumerWorker implements Runnable{
private static final Produced DONE = new Produced();
private BlockingQueue<Produced> inputQueue;
public ConsumerWorker(BlockingQueue<Produced> inputQueue) {
this.inputQueue = inputQueue;
}
#Override
public void run() {
for (;;) {
try {
Produced item = inputQueue.take();
if (item == DONE) {
inputQueue.add(item); // keep in the queue so all workers stop
break;
}
// process `item`
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
To stop the workers, simply add ConsumerWorker.DONE to the queue.
In your code-block where you attempt to retrive element from the queue , use poll(time,unit) instead of the take().
try {
Object queueElement = inputQueue.poll(timeout,unit);
//process queueElement
} catch (InterruptedException e) {
if(!isRunning && queue.isEmpty())
return ;
}
By specifying appropriate values of timeout , you ensure that threads wont keep blocking in case there is a unfortunate sequence of
isRunning is true
Queue becomes empty , so threads enter blocked wait ( if using take()
isRunning is set to false
Can not we do it using a CountDownLatch, where the size is the number of records in the producer. And every consumer will countDown after process a record. And its crosses the awaits() method when all tasks finished. Then stop all ur consumers. As all records are processed.
There are a number of strategies you could use, but one simple one is to have a subclass of task that signals the end of the job. The producer doesn't send this signal directly. Instead, it enqueues an instance of this task subclass. When one of your consumers pulls off this task and executes it, that causes the signal to be sent.
I had to use a multi-threaded producer and a multi-threaded consumer.
I ended up with a Scheduler -- N Producers -- M Consumers scheme, each two communicate via a queue (two queues total). The Scheduler fills the first queue with requests to produce data, and then fills it with N "poison pills". There is a counter of active producers (atomic int), and the last producer that receives the last poison pill sends M poison pills to the consumer queue.

Producer-consumer inter-thread communication

having trouble with inter-thread communication and "solved" it by using "dummy messages" all over the place. Is this a bad idea? What are possible solutions?
Example Problem i have.
main thread starts a thread for processing and inserting records into database.
main thread reads a possibly huge file and puts one record (object) after another into a blockingqueue. processing thread reads from queue and does work.
How do I tell "processing thread" to stop?
Queue can be empty but work is not done and the main thread does not now either when processing thread has finished work and can't interrupt it.
So processing thread does
while (queue.size() > 0 || !Thread.currentThread().isInterrupted()) {
MyObject object= queue.poll(100, TimeUnit.MILLISECONDS);
if (object != null) {
String data = object.getData();
if (data.equals("END")) {
break;
}
// do work
}
}
// clean-up
synchronized queue) {
queue.notifyAll();
}
return;
and main thread
// ...start processing thread...
while(reader.hasNext(){
// ...read whole file and put data in queue...
}
MyObject dummy = new MyObject();
dummy.setData("END");
queue.put(dummy);
//Note: empty queue here means work is done
while (queue.size() > 0) {
synchronized (queue) {
queue.wait(500); // over-cautios locking prevention i guess
}
}
Note that insertion must be in same transaction and transaction can't be handled
by main thread.
What would be a better way of doing this?
(I'm learning and don't want to start "doing it the wrong way")
These dummy message is valid. It is called "poison". Something that the producer sends to the consumer to make it stop.
Other possibility is to call Thread.interrupt() somewhere in the main thread and catch and handle the InterruptedException accordingly, in the worker thread.
"solved" it by using "dummy messages" all over the place. Is this a
bad idea? What are possible solutions?
It's not a bad idea, it's called "Poison Pills" and is a reasonable way to stop a thread-based service.
But it only works when the number of producers and consumers is known.
In code you posted, there are two threads, one is "main thread", which produces data, the other is "processing thread", which consumes data, the "Poison Pills" works well for this circumstance.
But to imagine, if you also have other producers, how does consumer know when to stop (only when all producers send "Poison Pills"), you need to know exactly the number of all the producers, and to check the number of "Poison Pills" in consumer, if it equals to the number of producers, which means all producers stopped working, then consumer stops.
In "main thread", you need to catch the InterruptedException, since if not, "main thread" might not able to set the "Poison Pill". You can do it like below,
...
try {
// do normal processing
} catch (InterruptedException e) { /* fall through */ }
finally {
MyObject dummy = new MyObject();
dummy.setData("END");
...
}
...
Also, you can try to use the ExecutorService to solve all your problem.
(It works when you just need to do some works and then stop when all are finished)
void doWorks(Set<String> works, long timeout, TimeUnit unit)
throws InterruptedException {
ExecutorService exec = Executors.newCachedThreadPool();
try {
for (final String work : works)
exec.execute(new Runnable() {
public void run() {
...
}
});
} finally {
exec.shutdown();
exec.awaitTermination(timeout, unit);
}
}
I'm learning and don't want to start "doing it the wrong way"
You might need to read the Book: Java Concurrency in Practice. Trust me, it's the best.
What you could do (which I did in a recent project) is to wrap the queue and then add a 'isOpen()'method.
class ClosableQ<T> {
boolean isOpen = true;
private LinkedBlockingQueue<T> lbq = new LinkedBlockingQueue<T>();
public void put(T someObject) {
if (isOpen) {
lbq.put(someObject);
}
}
public T get() {
if (isOpen) {
return lbq.get(0);
}
}
public boolean isOpen() {
return isOpen;
}
public void open() {
isOpen = true;
}
public void close() {
isOpen = false;
}
}
So your writer thread becomes something like :
while (reader.hasNext() ) {
// read the file and put it into the queue
dataQ.put(someObject);
}
// now we're done
dataQ.close();
and the reader thread:
while (dataQ.isOpen) {
someObject = dataQ.get();
}
You could of course extend the list instead but that gives the user a level of access you might not want. And you need to add some concurrency thingies to this code, like AtomicBoolean.

Stopping looping thread in Java

I'm using a thread that is continuously reading from a queue.
Something like:
public void run() {
Object obj;
while(true) {
synchronized(objectsQueue) {
if(objectesQueue.isEmpty()) {
try {
objectesQueue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
obj = objectesQueue.poll();
}
}
// Do something with the Object obj
}
}
What is the best way to stop this thread?
I see two options:
1 - Since Thread.stop() is deprecated, I can implement a stopThisThread() method that uses a n atomic check-condition variable.
2 - Send a Death Event object or something like that to the queue. When the thread fetches a death event, it exits.
I prefer the 1st way, however, I don't know when to call the stopThisThread() method, as something might be on it's way to the queue and the stop signal can arrive first (not desirable).
Any suggestions?
The DeathEvent (or as it is often call, "poison pill") approach works well if you need to complete all of the work on the queue before shutting down. The problem is that this could take a long time.
If you want to stop as soon as possible, I suggest you do this
BlockingQueue<O> queue = ...
...
public void run() {
try {
// The following test is necessary to get fast interrupts. If
// it is replaced with 'true', the queue will be drained before
// the interrupt is noticed. (Thanks Tim)
while (!Thread.interrupted()) {
O obj = queue.take();
doSomething(obj);
}
} catch (InterruptedException ex) {
// We are done.
}
}
To stop the thread t that instantiated with that run method, simply call t.interrupt();.
If you compare the code above with other answers, you will notice how using a BlockingQueue and Thread.interrupt() simplifies the solution.
I would also claim that an extra stop flag is unnecessary, and in the big picture, potentially harmful. A well-behaved worker thread should respect an interrupt. An unexpected interrupt simply means that the worker is being run in a context that the original programmer did not anticipate. The best thing is if the worker to does what it is told to do ... i.e. it should stop ... whether or not this fits with the original programmer's conception.
Why not use a scheduler which you simply can stop when required? The standard scheduler supports repeated scheduling which also waits for the worker thread to finish before rescheduling a new run.
ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
service.scheduleWithFixedDelay(myThread, 1, 10, TimeUnit.SECONDS);
this sample would run your thread with a delay of 10 sec, that means when one run finishes, it restarts it 10 seconds later. And instead of having to reinvent the wheel you get
service.shutdown()
the while(true) is not necessary anymore.
ScheduledExecutorService Javadoc
In your reader thread have a boolean variable stop. When you wish for this thread to stop set thius to true and interrupt the thread. Within the reader thread when safe (when you don't have an unprocessed object) check the status of the stop variable and return out of the loop if set. as per below.
public class readerThread extends Thread{
private volitile boolean stop = false;
public void stopSoon(){
stop = true;
this.interrupt();
}
public void run() {
Object obj;
while(true) {
if(stop){
return;
}
synchronized(objectsQueue) {
if(objectesQueue.isEmpty()) {
try {
objectesQueue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
if(stop){
return;
}
obj = objectesQueue.poll();
// Do something with the Object obj
}
}
}
}
public class OtherClass{
ThreadReader reader;
private void start(){
reader = ...;
reader.start();
}
private void stop(){
reader.stopSoon();
reader.join(); // Wait for thread to stop if nessasery.
}
}
Approach 1 is the preferred one.
Simply set a volatile stop field to true and call interrupt() on the running thread. This will force any I/O methods that wait to return with an InterruptedException (and if your library is written correctly this will be handled gracefully).
I think your two cases actually exhibit the same potential behavior. For the second case consider Thread A adds the DeathEvent after which Thread B adds a FooEvent. When your job Thread receives the DeathEvent there is still a FooEvent behind it, which is the same scenario you are describing in Option 1, unless you try to clear the queue before returning, but then you are essentially keeping the thread alive, when what you are trying to do is stop it.
I agree with you that the first option is more desirable. A potential solution would depend on how your queue is populated. If it is a part of your work thread class you could have your stopThisThread() method set a flag that would return an appropriate value (or throw Exception) from the enqueuing call i.e.:
MyThread extends Thread{
boolean running = true;
public void run(){
while(running){
try{
//process queue...
}catch(InterruptedExcpetion e){
...
}
}
}
public void stopThisThread(){
running = false;
interrupt();
}
public boolean enqueue(Object o){
if(!running){
return false;
OR
throw new ThreadNotRunningException();
}
queue.add(o);
return true;
}
}
It would then be the responsibility of the object attempting to enqueue the Event to deal with it appropriately, but at the least it will know that the event is not in the queue, and will not be processed.
I usually put a flag in the class that has the Thread in it and in my Thread code I would do. (NOTE: Instead of while(true) I do while(flag))
Then create a method in the class to set the flag to false;
private volatile bool flag = true;
public void stopThread()
{
flag = false;
}
public void run() {
Object obj;
while(flag) {
synchronized(objectsQueue) {
if(objectesQueue.isEmpty()) {
try {
objectesQueue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
obj = objectesQueue.poll();
}
}
// Do something with the Object obj
}
}

Categories

Resources