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.
Related
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).
I have this method which takes a thread as a parameter. I want this method to be able to make a thread wait if there is not one waiting already and then wake up when another thread comes into the method so that the two of them can interact. I think I'm close but after I call wait() on the first thread no other threads can gain access to that method. Here is a minimalist version of my code:
// In the class 'Node'
public synchronized void trade(Thread thread)
{
if (!threadWaiting)
{
threadWaiting = true;
synchronized(thread)
{
try {
thread.wait();
} catch (InterruptedException e) {...}
}
}
}
I apologise for missing anything obvious, I've been looking around for an answer but I'm new to threading so I've no idea what to look for.
So my problem is that when another thread attempts to get into trade() they can't, the debugger just stops right there.
EDIT:
Here's some more clarification on what I'm asking. I'm afraid I wasn't too clear in my original post.
So I have one class called Node and another class called Bot. Bot extends thread so that it can be paused. At the start of the program multiple Bot objects are created and are then started, each Bot will then call the trade() method of the Node and pass itself to the method. If a Bot is the first in the method then I want its thread to wait on the Node until another Bot comes along (The waiting Bot will be stored in the Node), at which point the two Bots will interact.
Below is a clearer example of my method in pseudo code:
// Variable to hold the bot that is waiting.
private Bot waitingBot = null;
// Method belonging to Node.
public synchronized void trade(Bot currentBot)
{
if (waitingBot == null)
{
waitingBot = currentBot;
waitingBot.wait();
}
else
{
currentBot.interactWith(waitingBot);
waitingBot.notify();
waitingBot = null;
}
}
Sorry about the wording of my original post.
Your implementation has a flaw. You are taking lock on parameter passed which will be different for all Threads so they can't interact with wait notify.
EDIT: I am not sure what exactly your aim is but based on details this might help:
EDIT2: Added lock()
private final Lock lck = new ReentrantLock();
private final Condition cnd = lck.newCondition();
private final AtomicBoolean threadwaiting = new AtomicBoolean(false);
public synchronized void trade(Thread thread)
{
lck.lock();
try{
if(threadwaiting.get()){
cnd.signalAll();
threadwaiting.set(false);
//perform your task
}else{
cnd.await();
threadwaiting.set(true);
}
}
} finally {
lck.unlock()
}
}
EDIT:
Looking at your updated post , you should use cyclicbarrier with count 2 then that should solve it all for you.
This is a dead lock, because when you call thread.wait(); you release thread object lock. But this object lock on synchronized method remains, that's why no one else can enter it.
It's like loki's code, but improved
private final Lock lock = new ReentrantLock();
private final Condition cnd = lock.newCondition();
private final AtomicBoolean threadwaiting = new AtomicBoolean(false);
public void trade(Thread thread) {
lock.lock();
if (threadwaiting.get()) {
cnd.signalAll();
lock.unlock();
// perform your task of second thread
} else {
threadwaiting.set(true);
try {
cnd.await();
// perform your task of first thread
} catch (InterruptedException e) {
} finally {
threadwaiting.set(false);
lock.unlock();
}
}
}
In my button execution, I am calling 2 methods.
plotButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
startPrinterListOperation();
showAplotPlotterDialog();
}
});
The startPrinterListOperation(); takes some time to complete its task. But I do not want the method showAplotPlotterDialog(); to run until the first one has completed. So I am trying to use thread management to achieve this. Here is what I have tried.
plotButton.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
Thread t = new Thread() {
public void run() {
startPrinterListOperation();
}
};
t.start();
try {
t.join();
}
catch (InterruptedException e1) {
e1.printStackTrace();
}
showAplotPlotterDialog();
}
});
But the second method stills starts before the first one has finished.
Extending on my comment: Seems like startPrinterListOperation launches an asynchronous operation and finishes instantly, evidented by the join succeeding.
If the launched async op is out of your control, then you might be able to observe it finishing via some callback, polling, etc. Then you may employ something like the following in startPrinterListOperation:
void startPrinterListOperation() {
final CountDownLatch c1 = new CountDownLatch(1);
launchTheAsyncOp(new SomeCallback() {
void x() {
c1.countDown();
}
});
try {
c1.await(999, TimeUnit.SECONDS)
}
catch (InterruptedException e) {
throw new MyRuntimeException("user didn't finish the op in 999 seconds, fail");
}
}
I would not bother with threads, this will just make your program overly complicated.
Can you edit the startPrinterListOperation() method?
I would instead add showAplotPlotterDialog(); to the end of the startPrinter method, and the last last thing the method does.
Answering your general question in the title, you have a master thread that calls your two methods directly, so that the second method waits for the first method to complete.
I understand that in your specific case, the first method runs for a while, and you would prefer that the user not have to wait.
You should call a generatePrinterList() method in a separate thread while you're constructing the GUI. You do this because your GUI users are very likely to print or plot, and the printer list is not likely to change while the user is using your GUI.
Odds are that the generatePrinterList() thread will finish long before your user has to print or plot. But just to be sure, the thread has to have a way of reporting back that the thread is completed. I use a boolean isCompleted that can be read with a public isCompleted() method.
The isCompleted() method could have a thread sleep loop if you want, so it always returns true. In this case the method doesn't have to return anything.
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
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.