public class MyContainer1 {
List<Object> lists = new ArrayList<>();
public void add(Object o) {
lists.add(o);
}
public int size() {
return lists.size();
}
}
public static void main(String[] args) {
MyContainer1 t1 = new MyContainer1();
new Thread(()->{
for(int i = 0; i < 10; i++) {
try {
t1.add("");
System.out.println(t1.size());
Thread.sleep(1000);
} catch (Exception e){
e.printStackTrace();
}
}
}, "t1").start();
new Thread(()->{
while (true) {
if(t1.size() == 5) {
System.out.println("list size is 5, break");
break;
}
}
}, "t2").start();
}
看起来是没问题,然而事情并不会这么简单,问题出在哪呢?忘记加volatile了!给lists加上volatile修饰:volatile List<Object> lists = new ArrayList<>();再运行程序,便能得到想要的效果。
但是这个程序就是完善的吗?当然不,其问题在于,线程2中的while循环,非常浪费CPU,另外就是,由于没有加同步,即使是while循环,也不能非常精准地在判断size为5的时候break,有可能在执行判断的时候,size又改了。所以,我们还需要做到更好!
这里使用wait和notify可以做到更好,wait会释放锁,而notify不会释放锁。
首先使用synchronized某个锁定对象,然后调用该对象的wait方法,线程进入等待状态,同时释放锁;只有在该对象的notify方法被调用的时候,等待状态的线程才会被唤醒继续执行。
事不宜迟,写下代码:
public class MyContainer2 {
private List<Integer> lists = new ArrayList<>();
public void add(Integer a) {
lists.add(a);
}
public Integer size() {
return lists.size();
}
public static void main(String[] args) {
MyContainer2 c = new MyContainer2();
final Object lock = new Object();