开发中有这样一个需求背景:controller有两个接口(线程)A、(线程)B。页面上需要同时调用这两个接口,这两个接口里都公用一个静态常量对象,要求接口B返回之前要等接口A对静态常量对象进行某些操作完才能返回。
解决方法:这时静态常量对象的wait方法和notify方法就可以上场了。
synchronized 用法参考https://blog.csdn.net/luoweifu/article/details/46613015
详细:
1.void notify()
唤醒在此对象监视器上等待的单个线程。
void notifyAll()
唤醒在此对象监视器上等待的所有线程。
void wait()
在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待。
2.使用这两个方法时,我们需要先有一个需要上锁的对象,配合synchronize使用
3.wait被执行后,锁自动被释放
notify被执行后,锁不会自动释放,必须执行完notify)方法所在的synchronized代码块后才释放
demo(可能和开头的需求背景不同,主要是能表达那个意思就行):
import org.springframework.beans.BeanUtils;
public class MyTest{
private static Money money = new Money();
public static void main(String[] args) {
//消费者线程
new Thread() {
@Override
public void run() {
System.out.println("消费者:老板,一份湿炒牛河。");
try {
Thread.sleep(1000);
synchronized (money) {
// obj.wait(10*1000);//可以设置最大等待时长。如果超过该时间就不等了,继续往后执行,在这时间内如果收到notify()或者notifyAll()就立即恢复往后执行
money.wait();//一直等,等到死那种
}
//唤醒后执行
Thread.sleep(1000);
System.out.println("消费者:嗯,好吃。");
System.out.println("有钱" + money.getMoney() + "元可以结账了");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
//老板线程
new Thread() {
@Override
public void run() {
System.out.println("老板:好嘞,您稍等。");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("老板:湿炒牛河,您慢用。");
Money newMoney = new Money();
newMoney.setMoney(100);
// 模拟数据更改
// money = newMoney;//特别注意这里,money = newMoney相当于改变了obj引用的对象,下面的synchronized (money)其实是对另一个对象加了锁,
// 并不是消费者那里加锁的那个全局常量money,这样会 导致消费者那里一直等待,正确方式应该用下面的BeanUtils.copyProperties(newMoney, money);;进行原对象的属性赋值操作
BeanUtils.copyProperties(newMoney, money);
//唤醒消费者
synchronized (money) {
money.notifyAll();
}
}
}.start();
}
}
注意点:
1,一定要是对同一个对象调用wait方法和notify方法
2, 中途不得修改对象的引用地址,可以用BeanUtils.copyProperties(newMoney, money)方法;
版权声明:本文为xc_nostalgia原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。