Dlaczego nie mogę otrzymać powiadomienia z reader
w tym kodzie:
public class ThreadMain {
public Thread reader;
private class SerialReader implements Runnable
{
public void run()
{
try
{
Thread.sleep(3000);
synchronized(this)
{
System.out.println("notifying");
notify();
}
Thread.sleep(3000);
} catch (Exception e){}
}
}
ThreadMain()
{
reader = (new Thread (new SerialReader()) );
}
public static void main(String [] args) {
ThreadMain d= new ThreadMain();
d.reader.start();
synchronized(d)
{
try
{
d.wait();
System.out.println("got notify");
} catch (Exception e) { System.out.println(e); }
}
}
}
Mam tylko linię notifying
na wyjściu
Odpowiedzi:
2 dla odpowiedzi № 1temu notify
i wait
nie używaj tego samego monitora, więc nie ma szans, aby „rozmawiali” ze sobą.
Jednym prostym rozwiązaniem jest użycie czytnika jako monitora w głównym:
synchronized (d.reader) {
try {
d.reader.wait();
System.out.println("got notify");
} catch (Exception e) {
System.out.println(e);
}
}
0 dla odpowiedzi nr 2
Twój wait()
i notify()
powinien być pod tym samym monitorem. Obecnie notify
W SerialReader
pod monitorem this
i wait
pod monitorem d
co jest ThreadMain
.
Przy okazji jedna rada notifyAll()
zamiast notify()
0 dla odpowiedzi № 3
W twoim Kodzie masz dwa problemy.
Jak sugerują inni. Musisz użyć tej samej blokady, aby korzystać z powiadomienia i czekać. Używasz różnych obiektów do oczekiwania i powiadamiania
Jest jeszcze jeden problem z twoim kodem, nawet jeśliużywasz prawidłowego monitora / blokad. Problem nazywa się Nieodebranymi Powiadomieniami, tzn. Twój wątek SerialReader może zakończyć się, zanim Twój Mainthread wykona metodę wait (), co spowoduje nieskończony sen Mainthread.
Rozwiązaniem obu powyższych problemów jest użycie zatrzasku. spróbuj CountDownLatch Zobacz poniżej
import java.util.concurrent.CountDownLatch;
MyClass klasy publicznej {
CountDownLatch latch = new CountDownLatch(1);
public MyClass(){
}
public void a() {
new Thread(new Runnable(){
@Override
public void run() {
System.out.println("A: I am going to sleep");
System.out.println("A: I slept one full day. Feels great.");
System.out.println("A: Hey B, wake up!");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
latch.countDown();
}
}).start();
}
public void b() {
new Thread(new Runnable(){
@Override
public void run() {
System.out.println("B: I am going to sleep. A, please wake me up.");
try {
latch.await();
} catch (InterruptedException e) {}
System.out.println("B: Thank you A for waking me up!");
}
}).start();
}
public static void main(String[] args) {
MyClass obj = new MyClass();
obj.a();
obj.b();
}
Powyższy kod pochodzi z mojej odpowiedzi na podobne pytanie