关于前面volatile 关键字的使用,我们会发现,t2监控到自己的情况之后,t1需要进行中断,然后等t2监控执行完成之后,才能继续执行,但是实际情况中,当并发量很大时候,我们会只想让t1发出一个通知,然后t1继续执行,不让t1产生中断,这样就需要我们加入lock锁:
下面是详细代码:
package com.SynchronizedExample;
import java.util.ArrayList;
import java.util.List;
public class ListAdd2 {
private volatile static List<String> list = new ArrayList<String>();
public void add() {
list.add("zhangsan");
}
public int size() {
return list.size();
}
public static void main(String[] args) {
final ListAdd2 list2 = new ListAdd2();
final Object lock = new Object();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (lock) {
for (int i = 0; i < 10; i++) {
list2.add();
System.out.println("当前线程:"
+ Thread.currentThread().getName()
+ "添加了一个元素..");
try {
Thread.sleep(200);
if (list2.size() == 5) {
System.out.println("已经发出通知..");
lock.notify();
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}, "t1");
Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
synchronized (lock) {
if (list.size() != 5) {
try {
lock.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("当前线程:"
+ Thread.currentThread().getName() + "收到通知, 线程停止");
throw new RuntimeException();
}
}
}, "t2");
t2.start();
t1.start();
}
}
注意,在这里,需要t2先执行,将锁的状态wait会释放锁,但是notify不释放,如果先执行t1,锁一直不会被释放,产生的结果就会是t1执行全部完成,然后t2进入等待状态,一直等待下去。
因此,需要先执行t2,将整个锁状态处于wait之下,然后执行t1,当t1执行到5的时候,向t2发出通知,t1继续进行,产生的结果是:
这样的结果,我们是做到了不影响t1 的执行,但是却有着不能实时监控缺陷,为了弥补这一缺陷,进一步参考下节:
CountDownLatch的使用。