I have a small question for you.
I have two threads:
HelloThread
- This prints "hello" five times.GoodbyeThread
- This prints "Goodbye" five times.
I would like the HelloThread
run first and after it's done the GoodbyeThread
run.
I have already solve this problem with semaphore (but semaphore doesn't really true java way, it's more C way).
HelloThread.java
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package modifiedthreadhellogoodbye;
import static java.lang.Thread.sleep;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.concurrent.Semaphore;
class HelloThread implements Runnable {
private final Object lock;
//private final Semaphore lock;
public HelloThread(Semaphore lock) {
this.lock = lock;
}
public HelloThread(Object lock) {
this.lock = lock;
}
@Override
public void run() {
int pause;
synchronized (lock) {
for (int i = 0; i < 5; i++) {
System.out.println("Hello!");
pause = (int) (Math.random() * 1000);
try {
sleep(pause);
} catch (InterruptedException ex) {
Logger.getLogger(HelloThread.class.getName()).log(Level.SEVERE, null, ex);
}
}
lock.notifyAll();
System.out.println("Outsite hello");
}
//lock.release();
}
}
GoodbyeThread.java
/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package modifiedthreadhellogoodbye;
import static java.lang.Thread.sleep;
import java.util.concurrent.Semaphore;
import java.util.logging.Level;
import java.util.logging.Logger;
class GoodbyeThread implements Runnable {
int pause;
//private final Semaphore lock;
private final Object lock;
public GoodbyeThread(Semaphore lock) {
this.lock = lock;
}
public GoodbyeThread(Object lock) {
this.lock = lock;
}
@Override
public void run() {
synchronized (lock) {
System.out.println("Inside the synchronized");
try {
lock.wait();
} catch (InterruptedException ex) {
Logger.getLogger(GoodbyeThread.class.getName()).log(Level.SEVERE, null, ex);
}
//lock.acquire();
for (int i = 0; i < 5; i++) {
System.out.println("Goodbye");
pause = (int) (Math.random() * 1000);
try {
sleep(pause);
} catch (InterruptedException ex) {
Logger.getLogger(GoodbyeThread.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
}
and this is my class who run thread :
public class ModifiedThreadObject {
private final Object lock = new Object();
//private final Semaphore lock = new Semaphore(0);
public ModifiedThreadObject() {
HelloThread hello = new HelloThread(lock);
GoodbyeThread goodbye = new GoodbyeThread(lock);
Thread t1 = new Thread(hello);
Thread t2 = new Thread(goodbye);
t1.start();
t2.start();
}
}
The main idea is GoodbyeThread
should wait()
for the signal from HelloThread
.
If GoodbyeThread
is run first, it's work perfectly, but HelloThread
runs first I have the following output:
Hello!
Hello!
Hello!
Hello!
Hello!
Outsite hello
Inside the synchronized
HelloThread
sends a notifyAll()
, but nobody is waiting so the "signal" is lost ...
Anybody have an idea?