前言
共享数据修改,是通过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需要等待,但不能无限等待,设置一个超时间,如果超时,那么返回超时,而不是一直等待。