package jack; public class ThreadA { private static Object lock = new Object(); private static Object lock1 = new Object(); public static void main(String[] args) { ThreadB threadB = new ThreadB(lock); threadB.start(); System.out.println("threadB is Start....."); synchronized (lock1) { ThreadC threadC = new ThreadC(lock); threadC.start(); /* try { */ System.out.println("Waiting for b to complete..."); /* threadB.wait(); */ /* * } catch (InterruptedException e) { // TODO Auto-generated catch * block } */ System.out.println("Total is :" + threadB.total); } } } class ThreadB extends Thread { Object object; ThreadB(Object object) { this.object=object; } int total = 0; public void run() { // TODO Auto-generated method stub synchronized (object) { System.out.println("ThreadB is running.."); for (int i = 0; i < 100; i++) { total += i; System.out.println("total is " + total); if (i == 50) { try { this.wait(); } catch (InterruptedException e) { } } try { Thread.sleep(30); } catch (InterruptedException e) { } } } } } class ThreadC extends Thread { Object obj = null; ThreadC(Object obj) { this.obj=obj; } int total = 0; public void run() { // TODO Auto-generated method stub synchronized (obj) { System.out.println("ThreadC is running.."); for (int i = 0; i < 100; i++) { total += i; System.out.println("TOTAL_C is " + total); try { Thread.sleep(30); } catch (InterruptedException e) { } } notify(); } } }
你同一个题目不用问两次吧。
把ThreadB类中的this.wait(); 改成 object.wait();
把ThreadC类中的notify(); 改成 object.notify();
这样就可以了。
原因是这样的,虽然wait是用来使当前线程阻塞并放弃锁,notify是用来唤醒阻塞线程。所以很多人自然而然的觉得应该用线程来调用wait/notify方法。
其实Thread类中是没有wait/notify方法的,只有Object中有。我们可以看看Object中wait()方法的API解释:
public final void wait() throws InterruptedException
在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待。换句话说,此方法的行为就好像它仅执行 wait(0) 调用一样。
当前线程必须拥有此[color=red]对象监视器[/color]。该线程发布对此监视器的所有权并等待,直到其他线程通过调用 notify 方法,或 notifyAll 方法通知在此对象的监视器上等待的线程醒来。然后该线程将等到重新获得对监视器的所有权后才能继续执行。
对于某一个参数的版本,实现中断和虚假唤醒是可能的,而且此方法应始终在循环中使用:
[color=red]synchronized (obj)[/color] {
while ()
[color=red]obj.wait();[/color]
... // Perform action appropriate to condition
}
此方法只应由作为此对象监视器的所有者的线程来调用。
抛出:
[color=red]IllegalMonitorStateException - 如果当前线程不是此对象监视器的所有者。 [/color]
InterruptedException - 如果在当前线程等待通知之前或者正在等待通知时,任何线程中断了当前线程。在抛出此异常时,当前线程的中断状态 被清除。
对象监视器指的是synchronized (obj)块的obj,也就是线程同步操作的公共区对象。想让一个线程等待,首先必须这个线程已经获得了对象监视器的锁。或者说已经在执行synchronized 块中的代码了,这时调用对象监视器的wait方法,才能够使得获得此对象监视器的线程等待,而不是直接用线程调用wait()方法。
当然,至于为什么this.wait()编译不报错,因为任何类都是Obeject的子类,所以都有wait()方法,但是this对象却不一定当前都占有了锁的。