How to make a Java thread wait for another thread's output?
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:
//do some work
synchronized(objectYouNeedToLockOn){
while (!dbThread.isReady()){
objectYouNeedToLockOn.wait();
}
}
//continue with work after dbThread is ready
In your dbThread
's method, you would need to do something like this:
//do db work
synchronized(objectYouNeedToLockOn){
//set ready flag to true (so isReady returns true)
ready = true;
objectYouNeedToLockOn.notifyAll();
}
//end thread run method here
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 separate Object
for that purpose (I would not recommend making the methods themselves synchronized):
private final Object lock = new Object();
//now use lock in your synchronized blocks
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 the java.util.concurrent
package and sub-packages. You really need to find material online to get to know concurrency, or get a good book.
Make one thread wait for another to finish
You call join
on the thread before it has started. That doesn't work; in that case, join
will return immediately, it's not going to wait until the other thread has started and stopped later. You can see this in the API documentation:
Thread.join()
This implementation uses a loop of
this.wait
calls conditioned onthis.isAlive
.
Thread.isAlive()
Tests if this thread is alive. A thread is alive if it has been started and has not yet died.
Reorder the statements in your main
method
t1.t.start();
t2.t.start();
t1.halt(t2.t); //wait for the 100-109 thread to finish
edit to answer your questions in the comments:
If you want the thread in AThread
to wait for the thread in BThread
to finish before doing its job, then you'll need to call join
in AThread.run
, and change your main
method:
class AThread implements Runnable {
Thread t;
Thread threadToWaitFor;
AThread(Thread threadToWaitFor) {
t = new Thread(this);
this.threadToWaitFor = threadToWaitFor;
}
public void run() {
// First wait for the other thread to finish
threadToWaitFor.join();
// ...
}
// ...
}
public class WaitForThread {
public static void main(String[] args) {
BThread t2 = new BThread();
AThread t1 = new AThread(t2.t);
t2.t.start();
t1.t.start();
}
}
How to make a thread wait for a server response
There are multiple concurrency primitives which allow you to implement thread communication. You can use CountDownLatch
to accomplish similar result:
public void waitForResponse() {
boolean result = latch.await(10, TimeUnit.SECONDS);
// check result and react correspondingly
}
public void notifyOKCommandReceived() {
latch.countDown();
}
Initialize latch before sending request as follows:
latch = new CountDownLatch(1);
How to make two thread wait for each other outcome?
I like your original approach of using wait / notifyAll to make the Thread doesn't use the CPU until the condition is met for it to resume running. Here's a solution that keeps this approach.
A few notes:
1 - Be careful when synchronizing on a class object. Unless you really want to synchronize the whole class, create an Object and use it as a lock.
2 - Use the volatile
keyword to ensure that Java doesn't create a thread local version of the variable and that changes to it's value are instantly reflected to other threads.
public class Threads {
private final Object lock = new Object();
private volatile boolean flag;
class RunnableA implements Runnable {
private volatile boolean condition = false;
@Override
public void run() {
while (true) {
if (condition) {
if (!flag) {
synchronized (lock) {
System.out.println("Setting Flag to True");
flag = true;
lock.notifyAll();
}
}
} else {
System.out.println("Condition is False");
try {
Thread.sleep(500);
} catch (InterruptedException ex) {
}
}
}
}
}
class RunnableB implements Runnable {
@Override
public void run() {
while (true) {
while (flag == false) {
synchronized (lock) {
if (flag == false) {
try {
lock.wait();
} catch (InterruptedException ex) {
}
}
}
}
System.out.println("Kaboom");
}
}
}
public void run() {
RunnableA runnableA = new RunnableA();
RunnableB runnableB = new RunnableB();
Thread t1 = new Thread(runnableA);
Thread t2 = new Thread(runnableB);
t1.start();
t2.start();
try {
Thread.sleep(5000L);
} catch (InterruptedException ex) {
}
runnableA.condition = true;
}
public static void main(String[] args) {
new Threads().run();
}
}
How to make thread wait if prerequisite was not yet done processing and resumes once prerequisite is finished?
I made my implementation simpler.
In my callable object, I do these.
@Override
public String call() throws Exception {
while (!ThreadApp.finishedProcess.containsAll(eodProcess.getPrerequisites())) {
System.out.println(eodProcess.getProcess() + " still waiting for prerequisites...");
Thread.sleep(3000);
}
System.out.println(eodProcess.getProcess() + " working...");
System.out.println(eodProcess.getProcess() + " done!");
ThreadApp.finishedProcess.add(eodProcess.getProcess());
return eodProcess.getProcess();
}
Thank you all for your help!
Related Topics
Difference Between Paint, Paintcomponent and Paintcomponents in Swing
Java - Class.Getresource Returns Null
How to Copy a 2 Dimensional Array in Java
How to Start/Stop/Restart a Thread in Java
How to Handle Iframe in Selenium Webdriver Using Java
How to Correctly Get Image from 'Resources' Folder in Netbeans
Java: Ternary with No Return. (For Method Calling)
How to Make a Jframe Modal in Swing Java
How to Execute System Commands (Linux/Bsd) Using Java
Garbage Collection of String Literals
Best Practice for Setting Jframe Locations
Java Default Crypto/Aes Behavior
Simplest Way to Set Image as JPAnel Background