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();//唤醒拥有同一个监视器的其他同步线程
}
}
}
}