在使用wait/notify模式时,还需要注意一种情况,即wait 条件发生变化,容易造成逻辑的混乱。创建类Add.java
package chapter3.test3_1.test3_1_18;
public class Add {
private String lock;
public Add(String lock) {
super();
this.lock = lock;
}
public void add() {
synchronized (lock) {
ValueObject.list.add("anyString");
lock.notifyAll();
}
}
}
创建类Subtract.java
package chapter3.test3_1.test3_1_18;
public class Subtract {
private String lock;
public Subtract(String lock) {
super();
this.lock = lock;
}
public void subtract() {
try {
synchronized (lock) {
if (ValueObject.list.size() == 0) {
System.out.println("wait begin ThreadName=" + Thread.currentThread().getName());
lock.wait();
System.out.println("wait end ThreadName=" + Thread.currentThread().getName());
}
ValueObject.list.remove(0);
System.out.println("list size=" + ValueObject.list.size());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
类ValueObject.java代码
package chapter3.test3_1.test3_1_18;
import java.util.ArrayList;
import java.util.List;
public class ValueObject {
public static List list = new ArrayList();
}
两个线程类代码
package chapter3.test3_1.test3_1_18;
public class ThreadAdd extends Thread {
private Add p;
public ThreadAdd(Add p) {
super();
this.p = p;
}
@Override
public void run() {
p.add();
}
}
package chapter3.test3_1.test3_1_18;
public class ThreadSubtract extends Thread {
private Subtract r;
public ThreadSubtract(Subtract r) {
super();
this.r = r;
}
@Override
public void run() {
r.subtract();
}
}
类Run.java代码
package chapter3.test3_1.test3_1_18;
public class Run {
public static void main(String[] args) throws InterruptedException {
String lock = new String("");
Add add = new Add(lock);
Subtract subtract = new Subtract(lock);
ThreadSubtract subtract1Thread = new ThreadSubtract(subtract);
subtract1Thread.setName("subtract1Thread");
subtract1Thread.start();
ThreadSubtract subtract2Thread = new ThreadSubtract(subtract);
subtract2Thread.setName("subtract2Thread");
subtract2Thread.start();
Thread.sleep(1000);
ThreadAdd addThread = new ThreadAdd(add);
addThread.setName("addThread");
addThread.start();
}
}
程序运行结果
出现异常的原因
出现异常的原因是有两个实现删除remove()操作的线程,它们在 “Thread.sleep ( 1000 ); ” 之前都执行了wait()方法,呈等待状态,当加操作的线程在1s之后被运行时,通知了所有呈等待状态的减操作线程,那么第一个实现减操作的线程能正确地删除 list 中索引为 0的数据,但第二个实现减操作的线程则出现索引溢出的异常,因为list中仅仅添加了一个数据,也只能删除一个数据,没有第二个数据可供删除,所以出现了java.lang.Index-OutOfBoundsException 异常。如何解决这种情况呢?更改Subtract.java中的subtract方法代码
package chapter3.test3_1.test3_1_18.test1;
public class Subtract {
private String lock;
public Subtract(String lock) {
super();
this.lock = lock;
}
public void subtract() {
try {
synchronized (lock) {
while (ValueObject.list.size() == 0) {
System.out.println("wait begin ThreadName=" + Thread.currentThread().getName());
lock.wait();
System.out.println("wait end ThreadName=" + Thread.currentThread().getName());
}
ValueObject.list.remove(0);
System.out.println("list size=" + ValueObject.list.size());
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
程序运行结果
不再出现异常



