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线程睡眠了一秒还是只有一个线程被唤醒
时间: 2024-04-03 22:35:47 浏览: 32
在这个代码中,ThreadA 线程在调用 `notifyAll()` 方法之前睡眠了 1 秒,这是为了确保 ThreadB 线程已经进入了等待状态。在 ThreadA 线程调用 `notifyAll()` 方法之后,所有在 ThreadA 对象上等待的线程都会被唤醒,并开始争夺 ThreadA 对象的锁。由于 ThreadB 线程共有三个,它们在唤醒后会同时尝试获取 ThreadA 对象的锁。在这里,由于只有一个线程能够获取到锁并开始执行,所以只有一个线程能够打印出自己的编号和 num 值。其他两个线程会继续等待,直到下一次被唤醒。因此,只有一个线程被唤醒。
相关问题
package Unit4; class ThreadA extends Thread{ public int num = 0; public void run(){ synchronized (this){ //在此类对象上实现同步,this 指代当前对象 for (int i= 0;i<3;++i) this.num += i; notifyAll();//通知所有在这个对象是等待的线程开始执行,在这里就是通知 TestNotify //主线程开始执行 } } public int getNum(){ return this.num; } } public class TestNotify extends Thread{ public static void main(String[] args) { ThreadA threada = new ThreadA(); threada.start(); //threada 线程有执行资格,但是还没有开始执行 synchronized (threada){ try { threada.wait(); //主线程等待 threada 线程执行结束才开始执行 // 而且只有获得了当前 threada 对象的锁之后才能执行 wait,就是说在同步域内才可以执行wait, //执行wait 后放弃对象锁 }catch (InterruptedException e){ e.printStackTrace(); } } System.out.println(threada.getNum()); } }
这段代码是一个简单的线程同步的例子,其中包括 ThreadA 和 TestNotify 两个类。
ThreadA 继承了 Thread 类,并且实现了 run 方法。在 run 方法中,使用 synchronized(this) 实现了对当前对象的同步。该同步块中使用 for 循环累加了 num 变量的值,并在循环结束后使用 notifyAll() 方法通知所有等待在该对象上的线程继续执行。
TestNotify 类中的 main 方法中,首先实例化了一个 ThreadA 对象 threada,并且调用了它的 start 方法启动线程。接着,在 synchronized 块中调用了 threada 的 wait 方法,使得主线程等待 threada 线程执行结束后才开始执行。最后,输出 threada.getNum() 的值。
这段代码的作用是实现了对线程的同步控制,确保了线程的执行顺序。
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()); } }为什么“我还是执行了”能被输出
在`ThreadA`线程中,我们使用了`synchronized`关键字来锁住对象,并在其中进行了运算,但是没有调用`notify()`或`notifyAll()`方法唤醒其他等待该对象锁的线程。
在主线程中,我们使用`synchronized`关键字锁住了`ThreadA`对象,并调用了`wait()`方法等待该对象的锁。当`ThreadA`线程执行完同步块中的运算后,释放了该对象锁,主线程获得了该对象锁并继续执行,输出了“我还是执行了”。
这里需要注意的是,主线程获得了`ThreadA`对象锁后,才能输出“我还是执行了”。如果`ThreadA`线程在主线程调用`wait()`方法前就已经执行完同步块并释放了锁,那么主线程就无法等待`ThreadA`线程的通知,也就无法输出“我还是执行了”。
阅读全文