class ThreadA extends Thread { public int num = 0; public void run() { synchronized (this) { for (int i = 0; i < 3; ++i) this.num += i; // notifyAll(); } } public int getNum() { return this.num; } } public class TestNotify extends Thread { public static void main(String[] args) { ThreadA threada = new ThreadA(); threada.start(); synchronized (threada){ try { threada.wait(); System.out.println("我还是执行了"); }catch (InterruptedException e){ e.printStackTrace(); } } System.out.println(threada.getNum()); } }为什么“我还是执行了”能被输出
时间: 2024-04-02 09:31:27 浏览: 11
在`ThreadA`线程中,我们使用了`synchronized`关键字来锁住对象,并在其中进行了运算,但是没有调用`notify()`或`notifyAll()`方法唤醒其他等待该对象锁的线程。
在主线程中,我们使用`synchronized`关键字锁住了`ThreadA`对象,并调用了`wait()`方法等待该对象的锁。当`ThreadA`线程执行完同步块中的运算后,释放了该对象锁,主线程获得了该对象锁并继续执行,输出了“我还是执行了”。
这里需要注意的是,主线程获得了`ThreadA`对象锁后,才能输出“我还是执行了”。如果`ThreadA`线程在主线程调用`wait()`方法前就已经执行完同步块并释放了锁,那么主线程就无法等待`ThreadA`线程的通知,也就无法输出“我还是执行了”。
相关问题
class ThreadA2 extends Thread { public int num = 0; public void run() { System.out.println(getName()); synchronized (this) { for (int i = 0; i < 3; ++i) this.num += i; } } public int getNum() { return this.num; } } public class TestNotify2 extends Thread { public static void main(String[] args) { ThreadA2 thread = new ThreadA2(); thread.start(); synchronized (thread){ try { thread.wait(); }catch (InterruptedException e){ e.printStackTrace(); } } } }代码为什么主线程没有被通知确还是执行了
在主线程中使用了 `wait()` 方法,这会使主线程进入等待状态,并释放对 `thread` 对象的锁。当 `thread` 对象调用 `notify()` 方法时,会通知正在等待 `thread` 对象锁的线程(即主线程)继续执行,但是在此之前,`thread` 对象的锁已经被释放,所以主线程并没有被通知而继续执行了。要想主线程能够被通知到,可以在主线程中使用一个标志位来判断是否被通知,或者使用 `notifyAll()` 方法来通知所有等待的线程。
class ThreadA extends Thread{ public int num = 0; public void run(){ synchronized (this){ //在此类对象上实现同步,this 指代当前对象 for (int i= 0;i<3;++i) this.num += i; try { Thread.sleep(1000); //如果ThreadA的三个示例线程在还没有进入等待状态之前就受到了notifyAll的信号 //那将会发生严重后果,因为调用notifyAll的线程只可以调用一次notifyAll,那将会造成等待 //的线程永远等待下去 //所以在此处让它小睡一会,让其他线程有时间进入等待状态 }catch (InterruptedException e){ e.printStackTrace(); } notifyAll();//通知所有在这个对象是等待的线程开始执行,在这里就是通知 TestNotify //主线程开始执行 } } public int getNum(){ return this.num; } } class ThreadB extends Thread{ private ThreadA threada; public ThreadB (ThreadA ta){ this.threada = ta; } public void run(){ System.out.println(Thread.currentThread().getName()+" is waiting."); synchronized (threada){ try { threada.wait(); }catch (InterruptedException e){ e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+" "+this.threada.getNum()); } } } public class TestNotify extends Thread{ public static void main(String[] args) { ThreadA threada = new ThreadA(); new ThreadB(threada).start(); new ThreadB(threada).start(); new ThreadB(threada).start(); threada.start(); } }代码有什么错误
这段代码没有明显的语法错误,但是存在一个潜在的逻辑问题。
在ThreadA的run()方法中,notifyAll()方法被调用的位置可能会导致问题。如果三个ThreadB实例还没有进入等待状态,就会错过notifyAll()方法的通知,导致它们永远处于等待状态。
为了解决这个问题,可以将notifyAll()方法的调用放在ThreadB的run()方法中。每个ThreadB实例都会等待ThreadA对象的notify()方法来通知它们继续执行,而不是等待ThreadA的notifyAll()方法。修改后的代码如下:
```
class ThreadA extends Thread{
public int num = 0;
public void run(){
synchronized (this){
for (int i= 0;i<3;++i) this.num += i;
try {
Thread.sleep(1000);
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
public int getNum(){
return this.num;
}
}
class ThreadB extends Thread{
private ThreadA threada;
public ThreadB (ThreadA ta){
this.threada = ta;
}
public void run(){
System.out.println(Thread.currentThread().getName()+" is waiting.");
synchronized (threada){
try {
threada.wait();
}catch (InterruptedException e){
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+" "+this.threada.getNum());
threada.notify();
}
}
}
public class TestNotify extends Thread{
public static void main(String[] args) {
ThreadA threada = new ThreadA();
ThreadB tb1 = new ThreadB(threada);
ThreadB tb2 = new ThreadB(threada);
ThreadB tb3 = new ThreadB(threada);
tb1.start();
tb2.start();
tb3.start();
try {
Thread.sleep(1000); //等待一段时间,确保ThreadB都处于等待状态
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (threada) {
threada.notifyAll();
}
}
}
```