假设有三个线程ABC,A为生产者线程,B为消费者线程,C为破坏者线程。三个线程都访问一个共享对象,C进入的时候,通过调用
notifyAll的方法,把所有的wait唤醒,如果用了if,代码会往下进行,会导致无法获取到元素或者删除元素。如果是while就不一样了,就会继续检查条件。
1.容器类EventStoage.java
package sss;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
public class EventStorage {
private int maxSize;
private List<Date> storage;
public EventStorage(){
maxSize=1;
storage=new LinkedList<>();
}
public synchronized void destory() {
notifyAll();
}
public synchronized void set(){
if (storage.size()==maxSize){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
((LinkedList<Date>) storage).offer(new Date());
System.out.printf("Set: %d\n",storage.size());
notifyAll();
}
public synchronized void get(){
if (storage.size()==0){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.printf("Get: %d: %s\n",storage.
size(),((LinkedList<?>)storage).poll());
notifyAll();
}
}
2.生产者
package sss;
public class Producer implements Runnable {
private EventStorage storage;
public Producer(EventStorage storage){
this.storage=storage;
}
@Override
public void run() {
for (int i=0; i<10; i++){
storage.set();
}
}
}
3.消费者
package sss;
public class Consumer implements Runnable {
private EventStorage storage;
public Consumer(EventStorage storage){
this.storage=storage;
}
@Override
public void run() {
for (int i=0; i<10; i++){
storage.get();
}
}
}
4.测试类
package sss;
public class Main {
public static void main(String[] args) {
EventStorage storage=new EventStorage();
Producer producer=new Producer(storage);
Thread A=new Thread(producer);
Consumer consumer=new Consumer(storage);
Thread B=new Thread(consumer);
A.start();
//破坏者线程C
Thread C=new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
storage.destory();
}
});
B.start();
C.start();
}
}
测试结果:
当然,你也可能不出错,因为线程的运行时机是不定的。
如果你把if改成while,就不会出现线程安全问题了,测试结果如下