线程之间的友好通信等待唤醒机制(wait\notify)
wait:调用wait方法,是当前线程从运行状态转变为阻塞状态,使用wait方法必须要有锁的支持,当前线程必须要有调用该方法的对象的监视器(也就是说该线程使用的同步锁必须与调用wait方法的对象保持一致)。
notify:唤醒拥有同一个监听器的其他同步线程(当然只会唤醒一个,由JVM决定);
错误代码:
wait方法和notify方法,用于同一个监听器的同步线程,而同步方法的锁是当前对象,也就是SubThread对象。
wait和notify方法与同步方法使用的不是同一个锁,因此报如下错误:
解决方法:使用同步代码块
如下:
wait:调用wait方法,是当前线程从运行状态转变为阻塞状态,使用wait方法必须要有锁的支持,当前线程必须要有调用该方法的对象的监视器(也就是说该线程使用的同步锁必须与调用wait方法的对象保持一致)。
notify:唤醒拥有同一个监听器的其他同步线程(当然只会唤醒一个,由JVM决定);
错误代码:
class SubThread implements Runnable { private Demo demo; public SubThread(Demo demo) { this.demo = demo; } @Override public synchronized void run() {//错误原因:使用的是同步方法,该方法锁是:this while (true) { try { if (demo.flag) { demo.wait();//而这里却是demo对象 } } catch (InterruptedException e) { // } for (int i = 0; i < 10; i++) { demo.i++; System.out.println(Thread.currentThread().getName() + "----" + demo.i); } demo.flag = true; demo.notify(); } } }原因分析:
wait方法和notify方法,用于同一个监听器的同步线程,而同步方法的锁是当前对象,也就是SubThread对象。
wait和notify方法与同步方法使用的不是同一个锁,因此报如下错误:
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException at java.lang.Object.notify(Native Method) at com.day27.test.SubThread.run(Test2.java:67) at java.lang.Thread.run(Thread.java:619)
解决方法:使用同步代码块
如下:
class Test{ public static void main(String[] args) { Demo demo = new Demo(); SubThread sub = new SubThread(demo); Thread thread = new Thread(sub); thread.start(); while (true) { synchronized (demo) {//由于两个线程同步操作dmeo对象,因此两个线程的同步锁必须是同一个对象并且是demo if (!demo.flag) {//当flag为false时,阻塞当前线程 try { demo.wait();//由dmeo对象调用wait方法 } catch (InterruptedException e) { // } } for (int i = 0; i < 100; i++) { demo.i++; System.out.println(Thread.currentThread().getName() + "----" + demo.i); } demo.flag = false;//执行完主线程,设置flag为false demo.notify();//唤醒拥有同一个对象demo的监听器的其他同步线程 } } } }
class Demo { public boolean flag;//线程友好通信的标志 public int i;//两个线程共享的数据 } class SubThread implements Runnable { private Demo demo; public SubThread(Demo demo) { this.demo = demo; } @Override public void run() { while (true) { synchronized (demo) {//同步锁对象 try { if (demo.flag) {//当flag为true时,使子线程处于阻塞状态 demo.wait();//调用wait方法,是当前线程处于阻塞状态 } } catch (InterruptedException e) { // } for (int i = 0; i < 10; i++) { demo.i++; System.out.println(Thread.currentThread().getName() + "----" + demo.i); } demo.flag = true;//当子线程执行完成后,设置flag为true demo.notify();//唤醒拥有同一个监视器的其他同步线程 } } } }