6-线程协作wait,notify,notifyall(实现等待通知)

前言

共享数据修改,是通过sync volatile threadlocal 等实现
当一个线程的值修改,那么另一个线程需要感知这个线程的修改 :即使线程通讯,那么就需要线程协作
1、用轮询,隔15分钟去查看
a 很难确保及时性
b 开销大,要一直去查看 浪费很多时间做无用功
2、设置一个闹钟,每次还是需要看查看闹钟
3、等待 通知机制
wait() notify() notifyAll(); 都是对象上的方法

一、wait,notify,notifyall

等待/通知规范
等待:
获取锁
循环条件是否满足,不满足wait()
满足处理逻辑
通知:
获取锁
改变条件
通知所有线程
等待线程模块:

while(!condition){ // 不能使用 if , 因为存在一些特殊情况, 使得线程没有收到 notify 时也能退出等待状态
    wait();
}
// do something

通知线程模块:

   // do something ...
   condition = true;
   notify();

为什么wait()和notify()首先加锁,因为这2个操作本来就是互斥的操作,如果不加锁
通知线程和等待线程启动后:等待线程先执行,执行while循环后,条件不满足,但还未执行wait()方法,通知线程改变了条件并执行了notify(),这时等待线程才执行wait()方法,这时就会错过通知 ,而一直处于无限等待,所以需要通过锁来使这2个方法互斥

public class Test {
    private boolean con;
    public Test() {
    }
    public Test(boolean c, String site) {
        this.con = c;
    }
    /* 改变条件*/
    public synchronized void changeCondition(){
    	this.con = true;
    	notifyAll();
    	//其他的业务代码
    }
    public synchronized void waitCondition(){
    	while(this.con) {
    		try {
				wait();
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
    	}
    }
}

最好使用notifyAll(),notify()会随机唤醒一个线程,可能发生信号丢失的情况,因数信息号可能被这个对象上等待的其它线程拦获。

等待超时机制

如果线程没有唤醒,那么会一直无限期的等待, 一般情况下,我们希望不许无限等待,在某一段时间比如10分钟后,拿到结果返回, 没拿到结果也返回,这种情况等待超时模式

//设置等待超时间
long overtime = now + T
//等待剩余时间
long remain = T;
//条件不满足,&& 没有超时
while(!condition&&remain>0){
   wait(remain);//如果等待时间没超时,被唤醒,那么计算一下等待剩余时间,while循环的时候,如果条件不满足,没有被超时,那么设置wait时间为剩余等待时间。
   remain = overtime - now;//计算剩余等待时间
}

使用场景:线程A获取一个数据库连接时,比如:连池大小10个,这10个连接被拿完,那么线程A需要等待,但不能无限等待,设置一个超时间,如果超时,那么返回超时,而不是一直等待。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值