Threaded BlockingQueue, clarification needed - java

When working with a BlockingQueue, i implemented the following logic to read from it until told otherwise. Unfortunately the following is happening, intermittently:
The problem:
Even after shouldContinueReading is set to false, loop does not CONSISTENTLY break
The problem is intermittent, sometimes everything works fine
As part of the QThread class, i declare:
public static volatile boolean shouldContinueReading = true;
Run (confirmed to be executing) method contains:
while (shouldContinueReading) {
try {
String retrieved = qIn.poll(2, TimeUnit.MILLISECONDS);
if (retrieved != null)
consume(retrieved);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("I am out"); // <-- not always seen
if (qIn.remainingCapacity() > 0) {
try {
consume(qIn.take());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
While this is going on, in another thread, when certain things happen, shouldContinueReading changes state
while (stillReading) {
// do nothing
}
QThread.shouldContinueReading = false;
Update: problem resolved
Turns out the problem lies a bit further:
private void consume(String take) {
// some processing
produce(newData.toString());
}
private void produce(String newData) {
System.out.println(newData);
try {
qOut.put(newData); // <-- Problem is here. Should use offer instead of put
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Both qIn (queue in) and qOut (queue out) are declared as:
private volatile BlockingQueue<String> qIn;
private volatile BlockingQueue<String> qOut;
The objects themselves are created elsewhere as follows and passed down to the constructor:
BlockingQueue<String> q1 = new SynchronousQueue<String>();
BlockingQueue<String> q2 = new SynchronousQueue<String>();
QThread qThread = new QThread(q1, q2);
Any suggestions? what i should do with qOut? Am i not declaring it correctly?

I bet QThread.shouldContinueReading = false; isn't getting executed always,or the reading thread is not executing in the first place. I.e. the problem you are seeing is likely somewhere up the stream -- not here. The first thing I'd do would be to pin down where exactly the problem lies, with 100% confidence (put some more print statements).
Apart from the problem, I'd recommend to use the thread interruption mechanism instead of rolling your own flag (which is, in turn just a glorified flag, but that way you can affect third party codes like BlockedQueue and make the implementation simpler and more efficient even) especially if this is production code.

Related

Java FutureTask - Multithreaded call to get()

I have the following two methods in a class:
private MyDef myDef;
private FutureTask<MyDef> defFutureTask;
public synchronized void periodEviction() {
myDef = null;
}
public MyDef loadMyItems() {
// if it's not ready use a future - it will block until the results are ready
if (this.myDef == null) { // this will still not be thread safe
Callable<MyDef> callableDef = ()->{ return this.loadFromDatabase(); };
FutureTask<MyDef> defTask = new FutureTask<>(callableDef);
this.defFutureTask = defTask;
defFutureTask.run();
}
try {
// wait until's it's ready
this.myDef = this.qDefFuture.get();
} catch(InterruptedException e) {
log.error(this.getClass(), "Interrupted whilst getting future..");
} catch(ExecutionException e) {
log.error(this.getClass(), "Error when executing callable future");
}
return this.myDef;
}
I wanted to do the following:
1) Do a cache eviction using periodEviction() every one hour or so.
2) Otherwise, use the cached value when db loading is done.
I believe I have misunderstood Java future as I couldn't answer the question, "What happens when Thread A,B,and C all are calling loadMyItems() at the same time?"
So does this mean without something like an executor, this implementation is still not thread safe?
An even simpler approach is to not cache the object at all but just retain the Future.
private CompletableFuture<MyDef> defFuture;
public synchronized void periodEviction() {
// evict by triggering the request anew
defFuture = CompletableFuture.supplyAsync(this::loadFromDatabase);
}
public synchronized Optional<MyDef> loadMyItems() {
try {
return Optional.of(this.defFuture.get());
} catch(InterruptedException e) {
log.error(this.getClass(), "Interrupted whilst getting future..");
} catch(ExecutionException e) {
log.error(this.getClass(), "Error when executing callable future");
}
return Optional.empty();
}
With the caveat that this will trigger the database query every eviction period rather than on demand.
A super simple approach would be to declare loadMyItems as synchronized. But if the class has other methods that access myDef, you would have to declare those synchronized too. Sometimes this results in very coarse-grained locking and slower performance.
If you're looking for the cleanest/fastest code, instead of declaring periodEviction as synchronized, declare myDef as an AtomicReference:
private final AtomicReference<MyDef> myDef = new AtomicReference<>();
Then the body of periodEviction is:
synchronized (myDef) {
myDef.set(null);
}
And the body of loadMyItems is:
synchronized (myDef) {
if (myDef.get() == null) {
// perform initialization steps, ending with:
myDef.set(this.qDefFuture.get());
}
return myDef.get();
}
If many threads call loadMyItems at the same time, myDef will only ever be initialized once, and they will all get the same object returned (unless somehow a call to periodEviction snuck in the middle).

Java: swing worker thread synchronization

In my application, I have one text field and a button. After focus lost from text field first swing worker (lets assume it as sw1) is called. Which opens a pop-up to populate value to put in text field. Second swing worker (lets assume it as sw2) is called after user clicks a button.
Now the issue is that if I write something in text field and then click on button, sw1 is started first to calculate the value to put in text field and at the same time sw2 is also started. And sw2 finishes first and then sw1 populates result. What I want is sw2 should wait for sw1 to finish. Once sw1 finishes its task, it will notify sw2.
I referred so many references over the internet and stackoverflow. This is the one which almost matches to my requirement.
I tried to create a static final object inside class which starts sw1:
public final static Object lockObject = new Object();
Then inside done() method of sw1, I have written code like:
synchronized(lockObject) {
sw1.notifyAll();
}
Inside doInBackground() method, of the second class, on first line, I have written code like:
synchronized(FirstClass.lockObject) {
try {
sw2.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
But I am getting java.lang.IllegalMonitorStateException, at java.lang.Object.notifyAll(Native Method). Can anybody tell me what is the issue and how to make it work the way I want.
Update: As per Ernest's solution I modified my code and it looks like now:
FirstClass.java
public final static Object lockObject = new Object();
public static boolean flag = false;
someMethod() {
synchronized(lockObject){
sw1.doInbackground() {
......
}
sw1.done() {
.....
flag = true;
lockObject.notifyAll();
}
}
}
SecondClass.java
anotherMethod() {
sw2.doInbackground() {
try {
while (!FirstClass.flag) {
FirstClass.lockObject.wait();
}
FirstClass.flag = false;
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
......
}
}
But still I am getting java.lang.IllegalMonitorStateException on lockObject.notifyAll() line. Can you please tell if I am doing it correctly?
Thanks.
Your code should look something like this.
FirstClass.java
public final static Object lockObject = new Object();
public static boolean flag = false;
someMethod() {
sw1.doInbackground() {
......
}
sw1.done() {
.....
}
synchronized(lockObject){
flag = true;
lockObject.notifyAll();
}
}
SecondClass.java
anotherMethod() {
sw2.doInbackground() {
try {
synchronized(lockObject){
while (!FirstClass.flag) {
FirstClass.lockObject.wait();
}
FirstClass.flag = false;
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
......
}
}
But. Synchronizing on a global static object will get you in trouble if you have more than one instance of FirstClass.java and SecondClass.java. You should really find a way to pass the object instances around.
If I understood correctly your use case, can't you simply disable the button for sw2 when the user starts editing the field, and re-enable it when the first worker finishes? It would be much more clear for the user as well.
You need not to reinvent such a simple synchronization facility. For example, you can use CountDownLatch. Sw1 does countdown and sw2 - await.
You can only call wait() and notify() on an object whose monitor you hold. In each of your code snippets, you're locking one object, but calling these methods on another. It just doesn't work that way. I'm afraid I can't quite make out what you're trying to do, so it's hard to give you specific corrections, but basically, these blocks need to look something like
synchronized(sw2) {
try {
sw2.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Let's say there are two threads, T1 and T2, and there is some object O1. Then if code running on thread T1 wants to wait until code in thread T2 says it's OK to continue, it must synchronize on object O1 and then call O1.wait(). When code running on T2 wants to send that message to T1, it must synchronize on O1 and call O1.notify() (or O1.notifyAll().) It doesn't matter what object you use for O1, but the code in both threads must agree to use the same object.

Thread Blocks in server mode

This method notifes an event loop to start processing a message. However, if the event loop is already processing a message then, this method blocks until it receives a notification of completed event processing (which is triggered at the end of the event loop).
public void processEvent(EventMessage request) throws Exception {
System.out.println("processEvent");
if (processingEvent) {
synchronized (eventCompleted) {
System.out.println("processEvent: Wait for Event to completed");
eventCompleted.wait();
System.out.println("processEvent: Event completed");
}
}
myRequest = request;
processingEvent = true;
synchronized (eventReady) {
eventReady.notifyAll();
}
}
This works in client mode. If I switch to server mode and the time spent in the event loop processing the message is too quick, then the method above blocks forever waiting for the event to completed. For some reason the event complete notification is sent after the processingEvent check and before the eventCompleted.wait(). It makes no difference if I remove the output statements. I can not repeat the same problem in client mode.
Why does this only happen in server mode and what can I do to prevent this happening?
Here is the eventReady wait and eventCompleted notification:
public void run() {
try {
while (true) {
try {
synchronized (eventReady) {
eventReady.wait();
}
nx.processEvent(myRequest, myResultSet);
if (processingEvent > 0) {
notifyInterface.notifyEventComplete(myRequest);
}
} catch (InterruptedException e) {
throw e;
} catch (Exception e) {
notifyInterface.notifyException(e, myRequest);
} finally {
processingEvent--;
synchronized (eventCompleted) {
eventCompleted.notifyAll();
}
}
} // End of while loop
} catch (InterruptedException Ignore) {
} finally {
me = null;
}
Here is revised code which seems to work without the deadlock problem - which BTW happened in client mode randomely after about 300 events.
private BlockingQueue<EventMessage> queue = new SynchronousQueue<EventMessage>();
public void processEvent(EventMessage request) throws Exception {
System.out.println("processEvent");
queue.put(request);
}
public void run() {
try {
while (true) {
EventMessage request = null;
try {
request = queue.take();
processingEvent = true;
nx.processEvent(request, myResultSet);
notifyInterface.notifyEventComplete(request);
} catch (InterruptedException e) {
throw e;
} catch (Exception e) {
notifyInterface.notifyException(e, request);
} finally {
if (processingEvent) {
synchronized (eventCompleted) {
processingEvent = false;
eventCompleted.notifyAll();
}
}
}
} // End of while loop
} catch (InterruptedException Ignore) {
} finally {
me = null;
}
}
If you call notifyAll and no thread is wait()ing, the notify is lost.
The correct approach is to always change a state, inside the synchronized block, when calling notify() and always check that state, inside the synchronized block, before calling wait().
Also your use of processingEvent doesn't appear to be thread safe.
Can you provide the code which waits on eventReady and notifies eventCompleted?
Your program can happen to work if your speed up or slow down your application just right e.g. if you use -client, but if you use a different machine, JVM or JVM options it can fail.
There are a number of race conditions in your code. Even declaring processingEvent volatile or using an AtomicBoolean won't help. I would recommend using a SynchronousQueue which will block the event until the processer is ready for it. Something like:
private final BlockingQueue<Request> queue = new SynchronousQueue<Request>();
...
// this will block until the processor dequeues it
queue.put(request);
Then the event processor does:
while (!done) {
// this will block until an event is put-ed to the queue
Request request = queue.take();
process the event ...
}
Only one request will be processed at once and all of the synchronization, etc. will be handled by the SynchronousQueue.
If processingEvent isn't declared volatile or accessed from within a synchronized block then updates made by one thread may not become visible to other threads immediately. It's not clear from your code whether this is the case, though.
The "server" VM is optimised for speed (at the expense of startup time and memory usage) which could be the reason why you didn't encounter this problem when using the "client" VM.
There is a race condition in your code that may be exasperated by using the server VM, and if processingEvent is not volatile then perhaps certain optimizations made by the server VM or its environment are further influencing the problem.
The problem with your code (assuming this method is accessed by multiple threads concurrently) is that between your check of processingEvent and eventCompleted.wait(), another thread can already notify and (I assume) set processingEvent to false.
The simplest solution to your blocking problem is to not try to manage it yourself, and just let the JVM do it by using a shared lock (if you only want to process one event at a time). So you could just synchronize the entire method, for instance, and not worry about it.
A second simple solution is to use a SynchronousQueue (this is the type of situation it is designed for) for your event passing; or if you have more executing threads and want more than 1 element in the queue at a time then you can use an ArrayBlockingQueue instead. Eg:
private SynchronousQueue<EventMessage> queue = new SynchronousQueue<EventMessage>();
public void addEvent(EventMessage request) throws Exception
{
System.out.println("Adding event");
queue.put(request);
}
public void processNextEvent()
{
EventMessage request = queue.take();
processMyEvent(request);
}
// Your queue executing thread
public void run()
{
while(!terminated)
{
processNextEvent();
}
}

Get and send messages with Java Threads

I want to make a thread, which runs, computes something with the data i give it, and returns a few values, or an object. The thread is a part of a Swing GUI.
My question: How can I make a method that runs when I make the thread, and returns an object (or whatever I want it to return)?
My code:
private void nextTurn () {
// do something
if (turn == white) {
try {
Engine e = new Engine(); // Engine is implemented by runnable
e.start();
Move m = e.getBestMove (board);
// thread should work, next code should be excecuted immediately
}
catch (Exception e) {}
}
// end of Main class
}
This is the first time I am working with Threads, and I know you should avoid them if possible, but I need it this time for my GUI.
The info on the Oracle site on Threads did not help me out. I am able to make a program with multiple Threads that runs indefinately, but I can't make it work with functions.
Since this is with a Swing GUI, consider using a SwingWorker object which creates a background thread (all the code run in the doInBackground method), and then can return a final result and/or interim results. Information on how to use this is well documented in the tutorials here:
Concurrency in Swing
SwingWorkers have property change support and thus will allow listeners to observe its state (as a SwingWorker.StateValue) via a PropertyChangeListener. This is one way your program can determine that the thread has completed its processing, get the returned result and go from there.
On an unrelated note, this isn't in your production code is it?:
catch (Exception e) {}
If so, you will likely want to fix this as ignored exceptions can bite you in the tail big time.
e.g.,
if (turn == white) {
try {
final SwingWorker<Move, Void> mySwingWorker = new SwingWorker<Move, Void>() {
#Override
protected Move doInBackground() throws Exception {
Engine e = new Engine(); // Engine is implemented by runnable
e.start();
Move m = e.getBestMove(board);
return m;
}
};
mySwingWorker.addPropertyChangeListener(new PropertyChangeListener() {
public void propertyChange(PropertyChangeEvent evt) {
if (StateValue.DONE == mySwingWorker.getState()) {
try {
Move m = mySwingWorker.get();
// TODO: insert code to run on the EDT after move determined
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
});
mySwingWorker.execute();
} catch (Exception e) {
e.printStackTrace();
}
}
I suggest you use an ExecutorService. It allows you to create a thread pool, you can pass tasks to it and get the results later.
http://download.oracle.com/javase/6/docs/api/java/util/concurrent/ExecutorService.html

How to lock a java method to protect multiple invocations

I have an application that every 15 minutes or so does a replication from a remote database. It just keeps the two repositories in sync. Once this replication is going it is not possible to do it again. I have setup the following structure but I'm not sure if it is the correct approach.
public class ReplicatorRunner {
private static Lock lock = new ReentrantLock();
public replicate() {
if (lock.tryLock()) {
try {
// long running process
} catch (Exception e) {
} finally {
lock.unlock();
}
} else {
throw new IllegalStateException("already replicating");
}
}
}
public class ReplicatorRunnerInvocator {
public void someMethod() {
try {
ReplicatorRunner replicator = new ReplicatorRunner();
replicator.replicate();
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
}
The ReplicatorRunner is the class owning the method replicate which can only be run one at a time.
Edit.
I need the next call to fail (not block) if the method is already running on any instance.
This looks good. ReentrantLock.tryLock() will only give the lock to one thread, so synchronized is not necessary. It also prevents the blocking inherent in synchronization that you say is a requirement. ReentrantLock is Serializable, so should work across your cluster.
Go for it.
Change public replicate() to public synchronized replicate()
That way replicate will only ever allow access to one thread at a time. You'll also be able to delete the ReentrantLock and all associated code.
I ended up using the following:
public class ReplicatorRunner {
private static Semaphore lock = new Semaphore(1);
public replicate() {
if (lock.tryAcquire()) {
try {
// basic setup
Thread t = new Thread(new Runnable() {
public void run() {
try {
// long running process
} catch Exception (e) {
// handle the exceptions
} finally {
lock.release();
}
}
})
t.start();
} catch (Exception e) {
// in case something goes wrong
// before the thread starts
lock.release();
}
} else {
throw new IllegalStateException("already replicating");
}
}
}
public class ReplicatorRunnerInvocator {
public void someMethod() {
try {
ReplicatorRunner replicator = new ReplicatorRunner();
replicator.replicate();
} catch (IllegalStateException e) {
e.printStackTrace();
}
}
}
Without looking at the specifics of the ReentrantLock, it occurs to me that this prevention of multiple simultaneous replication routines will be limited to a single JVM instance.
If another instance of the class is kicked off in a separate JVM, then you might be in trouble.
Why not put a lock mechanism on the database? i.e. A row in a control table that is set to a value depicting whether or not the replication is busy running, and reset the value when the replication is finished.
take a look at the Semaphore class here or mark the method as synchronized
the thread executing the method at any given time owns a lock on it avoiding other threads to call the method until its execution ends.
Edit: if you want the other threads to fail, you could use a Lock, and test if the lock is avaible by the tryLock method.

Categories