[英]How do I use wait() and notify() if I have one Runnable and one that implements Threads?
我要在第一個線程完成后開始第二個線程。 但是,如果線程的實現方式不同,我無法弄清楚如何使用wait()/ notify()函數。 首先嘗試在單獨的類中使用它,但是后來我無法讓第一個線程在完成時發出信號。
public class Oblig1 {
static void threadMessage(String message) {
String threadName =
Thread.currentThread().getName();
System.out.format("%s: %s%n",
threadName,
message);
}
private boolean start = false;
public void StartThread(){
start = true;
}
class Thread1 implements Runnable{
private int X;
Thread2 obj = new Thread2(5);
public Thread1(int x) {
X = x;
}
public synchronized void run() {
for (int i=1; i<21; i++) {
System.out.print(X*i + " ");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
threadMessage("I wasn't done!");
}
}
StartThread();
notifyAll();
}
}
class Thread2 extends Thread {
private int X;
public Thread2(int x) {
X = x;
}
public synchronized void run() {
while (!start){
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
for (int i=1; i<21; i++) {
System.out.print(X*i + " ");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
threadMessage("I wasn't done!");
}
}
notifyAll();
}
}
public static void main(String [ ] args) {
int inputT1 = 3;
int inputT2 = 5;
Thread t1 = new Thread(new Thread1(inputT1));
Thread t2 = new Thread(new Thread2(inputT2));
t1.start();
t2.start();
}
}
你等待某個對象,你通知某個對象(在當前的代碼你不指定對象,所以它是this
)。 結果,一個線程調用了自己的通知,但沒有人在等待它。 當Thread2等待自身時,沒有人喚醒它(因為沒有人調用此Thread2實例的通知)。
要喚醒Thread2,您需要在該對象(此對象)上調用notify,以便Thread1應該調用obj.notify()(因為obj在代碼中是Thread2)。
但是,它仍然不起作用,因為您沒有將Thread2實例傳遞給Thread1(您只是在Thread1中創建了一個新實例),所以您通知的線程2只是創建而從未啟動。 主線程中的Thread2已啟動,但從未收到通知。
可能的代碼修復
static class Thread1 extends Thread {
private int X;
final Thread2 second;
public Thread1(int x,Thread2 second) {
X = x;
this.second = second;
}
public void run() {
for(){
//....
}
second.start = true;
second.notify();
}
}
static class Thread2 extends Thread {
private int X;
public boolean start = false;
public Thread2(int x) {
X = x;
}
public void run() {
while(!start){
synchronized(this) {
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
for(){
....
}
}
}
public static void main(String [ ] args)
{
int inputT1 = 3;
int inputT2 = 5;
Thread2 t2 = new Thread2(inputT2);
Thread1 t1 = new Thread1(inputT1,t2);
t1.start();
t2.start();
}
wait()
和notify()
方法是低級原語,最好避免使用高級並發API。 滾動您自己的並發代碼可能會出現問題(例如,代碼中的start
字段必須是可變的!)。
一個簡單的解決方法是使用CountDownLatch
。 替換為:
private boolean start = false;
有了這個:
private final CountDownLatch latch = new CountDownLatch(1);
然后,而不是調用notifyAll()
而是調用latch.countDown();
Thread2的run
方法如下所示:
public void run() {
latch.await();
for (int i=1; i<21; i++) {
System.out.print(X*i + " ");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
threadMessage("I wasn't done!");
}
}
threadMessage("Done");
}
2個使用鎖/通知依次運行的線程的示例:
public class Thread2Test {
public static void main(String[] args)
{
final Object sync = new Object();
final Object lock = new Object();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
synchronized(lock) {
synchronized(sync) {
sync.notify(); // Notify main() to let it start t2.
}
for (int n=0; n<10; n++)
{
System.out.println(n);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
}
System.out.println("t1 finished.");
}
}
});
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("t2 started...");
synchronized(lock) {
// don't need to do anything but wait for lock to be released
}
char c = 'a';
for (int n=0; n<10; n++)
{
System.out.println(c);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
c++;
}
System.out.println("t2 finished.");
}
});
try {
System.out.println("Wait for t1 to start...");
synchronized(sync) {
t1.start();
sync.wait();
}
} catch (InterruptedException e) {
}
System.out.println("end wait");
t2.start();
}
請注意,同步對象用於確保t1始終在t2之前開始。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.