I'm making a Java application with an application-logic-thread and a database-access-thread. Both of them persist for the entire lifetime of the application and both need to be running at the same time (one talks to the server, one talks to the user; when the app is fully started, I need both of them to work).
However, on startup, I need to make sure that initially the app thread waits until the db thread is ready (currently determined by polling a custom method dbthread.isReady()
).
I wouldn't mind if app thread blocks until the db thread was ready.
Thread.join()
doesn't look like a solution - the db thread only exits at app shutdown.
while (!dbthread.isReady()) {}
kind of works, but the empty loop consumes a lot of processor cycles.
Any other ideas? Thanks.
Try CountDownLatch class out of the
java.util.concurrent
package, which provides higher level synchronization mechanisms, that are far less error prone than any of the low level stuff.I would really recommend that you go through a tutorial like Sun's Java Concurrency before you commence in the magical world of multithreading.
There are also a number of good books out (google for "Concurrent Programming in Java", "Java Concurrency in Practice".
To get to your answer:
In your code that must wait for the
dbThread
, you must have something like this:In your
dbThread
's method, you would need to do something like this:The
objectYouNeedToLockOn
I'm using in these examples is preferably the object that you need to manipulate concurrently from each thread, or you could create a separateObject
for that purpose (I would not recommend making the methods themselves synchronized):To further your understanding:
There are other (sometimes better) ways to do the above, e.g. with
CountdownLatches
, etc. Since Java 5 there are a lot of nifty concurrency classes in thejava.util.concurrent
package and sub-packages. You really need to find material online to get to know concurrency, or get a good book.The Future interface from the
java.lang.concurrent
package is designed to provide access to results calculated in another thread.Take a look at FutureTask and ExecutorService for a ready-made way of doing this kind of thing.
I'd strongly recommend reading Java Concurrency In Practice to anyone interested in concurrency and multithreading. It obviously concentrates on Java, but there is plenty of meat for anybody working in other languages too.
Use this class like this then:
Create a ThreadEvent:
In the method this is waiting for results:
And in the method that is creating the results after all the results have been created:
EDIT:
(Sorry for editing this post, but this code has a very bad race condition and I don't have enough reputation to comment)
You can only use this if you are 100% sure that signal() is called after await(). This is the one big reason why you cannot use Java object like e.g. Windows Events.
The if the code runs in this order:
then thread 2 will wait forever. This is because Object.notify() only wakes up one of the currently running threads. A thread waiting later is not awoken. This is very different from how I expect events to work, where an event is signalled until a) waited for or b) explicitly reset.
Note: Most of the time, you should use notifyAll(), but this is not relevant to the "wait forever" problem above.
You could read from a blocking queue in one thread and write to it in another thread.
This applies to all languages:
You want to have an event/listener model. You create a listener to wait for a particular event. The event would be created (or signaled) in your worker thread. This will block the thread until the signal is received instead of constantly polling to see if a condition is met, like the solution you currently have.
Your situation is one of the most common causes for deadlocks- make sure you signal the other thread regardless of errors that may have occurred. Example- if your application throws an exception- and never calls the method to signal the other that things have completed. This will make it so the other thread never 'wakes up'.
I suggest that you look into the concepts of using events and event handlers to better understand this paradigm before implementing your case.
Alternatively you can use a blocking function call using a mutex- which will cause the thread to wait for the resource to be free. To do this you need good thread synchronization- such as: