关于wait和notify的问题

香蕉波波球 2017-12-10 12:38:46
package com.bjsxt.base.conn008;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
/**
* @author wangyang
*
*/
public class ListAdd2 {
private volatile static List list = new ArrayList();

public void add(){
list.add("wangyang");
}
public int size(){
return list.size();
}

public static void main(String[] args) throws InterruptedException {


final ListAdd2 list2 = new ListAdd2();
final Object lock = new Object();
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
try {
synchronized (lock) {
System.out.println("t1启动..");
for(int i = 0; i <10; i++){
list2.add();
System.out.println("当前线程:" + Thread.currentThread().getName() + "添加了一个元素..");
Thread.sleep(500);
if(list2.size() == 5){
System.out.println("已经发出通知..");
lock.notify();
}
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}

}
}, "t1");

Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(list2.size());
synchronized (lock) {
System.out.println("t2启动..");

if(list2.size() != 5){
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("当前线程:" + Thread.currentThread().getName() + "收到通知线程停止..");
throw new RuntimeException();
}
}
}, "t2");

t2.start();
Thread.sleep(1000);

t1.start();
}

}



当list2.size==5时,唤醒t2线程,然后t1执行完后,t2拿到锁,可是此时list2.size已经是10了,为什么还是会执行下面的抛异常的代码呢?请各位大神指教一下,多谢

...全文
111 1 点赞 打赏 收藏 举报
写回复
1 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
Seeker-Wu 2017-12-11
根据你给出的代码我试着DEBUG运行了两次,那么输出结果图如下:

从图中我们可以看出首先输出的t1启动,然后是t2输出当前list的大小为0;
接着输出了t1添加元素,然后发出通知,继续添加到结束释放锁;
再下来是t2获取到锁然后启动并判断是list的大小为5,因为这个时候不是5所以会发出lock.wait()执行,然后一直等待。并不会执行之后的程序,所以就结束了。
然后我直接运行,而不是debug模式,则输出如下:

从图中明显可以看出首先是t2输出了list的大小为0;然后显示t2启动,因为这个时候t2拿到了锁,去判断,发现list的大小不是5所以会等待并释放锁;
然后我们看到t1获得锁并开始启动,然后添加元素发出通知,然后继续添加到结束,释放锁;
然后t2会获取到锁,那么这个时候,是否list的大小是5的判断并不会再次执行,因为你用的是if判断,而且他已经执行过了,所以就会直接执行之后的代码输出了:
当前线程t2收到了通知停止线程,并且接着抛出了异常。
因为t2的判断已经在第一次获得锁就执行了,第二次获得锁则直接运行之后的代码,所以会执行输出和抛出异常。
这理解你应该是和我图2得到的相同的结果,所以你看到了异常输出。
如果答案满意,望采纳。
  • 打赏
  • 举报
回复
相关推荐
发帖
Java EE
加入

6.7w+

社区成员

J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
申请成为版主
帖子事件
创建了帖子
2017-12-10 12:38
社区公告
暂无公告