在使用wait/notify模式时,还需要注意一种情况,即wait 条件发生变化,容易造成逻辑的混乱。
- 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();
- }
- }
- }
- 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();
- }
- }
- }
- 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();
- }
- }
- 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 异常。
- 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();
- }
- }
- }

不再出现异常