Java 多线程(Thread) 同步(synchronized) 以及 wait, notify 相关 [实例介绍]
场景描述
有一家很大的商场,在某市有几个商品配送中心,并有几家分店,这家商场经营很多的商品,平时运营情况是这样的:
根据各分店的商品销售情况,给分店配送相应需求量的商品;并上架到分店指让的位置,供客户选购。
客户选择自己需要的商品,然后到收银台交钱打包;
然后到一天的某个时候分店管理员(经理等),开始统计当前的销售情况,并计划向商品配送中心订购各商品的配送量;
场景模拟
1. 商场类;
public class StoreMart {
//商场这一天剩余的商品量
private static Map<String, Integer> goodsMap = new HashMap<String, Integer>();
private static Map<String, Integer> priceMap = new HashMap<String, Integer>();
static {
goodsMap.put("ap", 1000);
goodsMap.put("bp", 500);
goodsMap.put("cp", 2000);
priceMap.put("ap", 20);
priceMap.put("bp", 50);
priceMap.put("cp", 30);
//...
}
//选择商品
//pn 商品名称
//num 选购数量
public synchronized void selGoods(String name,String pn, int num) {
int total = getNum(pn);
int remain = total - num;
goodsMap.put(pn, remain);
//保存用户购物车信息
}
//新增商品数据
public synchronized void putGoods(String pn, int num) {
int total = getNum(pn);
total = total + num;
goodsMap.put(pn, total);
}
public static int getNum(String pn) {
int num = 0;
if (goodsMap.containsKey(pn)) {
num = goodsMap.get(pn);
}
return num;
}
//结算
public void settleGoods(Map<String, Integer> goods) {
//....
}
}
用户购物类:
public class UserShop implements Runnable {
private static StoreMart sm = new StoreMart();
private final String name;
private final Map<String, Integer> sgoods = new HashMap<String, Integer>();
public UserShop(String name) {
this.name = name;
}
public void add(String pn, int num) {
sgoods.put(pn, num);
}
public void run() {
for(Map.Entry<String, Integer> entry:sgoods.entrySet()){
sm.selGoods(entry.getKey(), entry.getValue());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
sm.settleGoods(sgoods);
System.out.println(this.name + " 购物完毕! ");
}
public static void main(String[] args) {
UserShop u1 = new UserShop("NameA");
u1.add("ap",1);
u1.add("bp",2);
Thread t1 = new Thread(u1);
UserShop u2 = new UserShop("NameB");
u1.add("ap",4);
u1.add("bp",5);
Thread t2 = new Thread(u2);
t1.start();
t2.start();
}
}
以上摸拟的是商品数量都充足的情况;
摸拟了两个客户 各购买了 不同数量的商品 ap, bp;
但是如果万一用户多了起来,如果有几个客户一下子要选购同一个商品很多的量;就会出问题了;
使用 wait(), notify()
修改 下 StoreMart 类:
//选择商品
//pn 商品名称
//num 选购数量
public synchronized void selGoods(String name,String pn, int num) {
int total = getNum(pn);
while (total < num) {
System.out.println(pn + "商品量不够");
this.wait();
}
int remain = total - num;
goodsMap.put(pn, total); //保存用户购物车信息
} //新增商品数据
public synchronized void putGoods(String pn, int num) {
int total = getNum(pn);
total = total + num;
goodsMap.put(pn, total);
this.notify();
}
在UserShop 的 run 方法里,添加商品不足补货的语句:
public void run() {
for(Map.Entry<String, Integer> entry:sgoods.entrySet()){
sm.selGoods(entry.getKey(), entry.getValue());
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//发现商品不够了
sm.putGoods("ap", 100);
sm.putGoods("bp", 200);
System.out.println(this.name + " 购物完毕! ");
}
这样 当商场里的 某商品量不足时,NameA 或 NameB 就得处于等待状态,就是要wait() 到等待集合,等待被 notify() 换醒;
synchronized, wait, notify说明
1. wait;
1>. 用于 当本 线程不能成立时,放弃当前占用的锁;
2>. wait 必须要在 synchronized 所在的代码块内;
3>. wait 是 Object 的方法;
4>. 一般要处理 while 循环 体内; 用于重新判断条件是否满足;
2. synchronized 一般结束多线程环境下,用于处理 占用 共享资源的问题;
3. notify 用于 唤醒 wait() 的线程;
wait 与 sleep 的区别
wait 针对的是 当前 synchronized 所在块的机锁:
1>. synchronized 如果 标识一个 普通类,那机锁就为当前 所在对象的 锁;
2>. synchronized 如果 标识一个 静态类,那机锁 就为所在类的类锁;
3>. 如果是 synchronized (obj) ,则 锁 为 obj 对象; 一般这个锁可以定义为 0 长度的 byte 数组,比较经济;
sleep 针的是当前 Thread;
sleep 一般是定时执行的;
wait 是需要竞争的,能否执行,得看本次锁是否分配给了它,本且条件是否满足;
interrupt() 都可以中止 sleep 或 wait 的暂停状态;如果线程 A 要中止 线程 B,则调用 线程B实例的 interrupt() 方法,当 线程B处于 wait(),sleep(),join() 时,就会抛出 InterruptedException 异常,在 catch 块执行 return ,即可正常结束线程;
Java 多线程(Thread) 同步(synchronized) 以及 wait, notify 相关 [实例介绍]的更多相关文章
- Java多线程5:Synchronized锁机制
一.前言 在多线程中,有时会出现多个线程对同一个对象的变量进行并发访问的情形,如果不做正确的同步处理,那么产生的后果就是“脏读”,也就是获取到的数据其实是被修改过的. 二.引入Synchronized ...
- Java多线程编程(同步、死锁、生产消费者问题)
Java多线程编程(同步.死锁.生产消费): 关于线程同步以及死锁问题: 线程同步概念:是指若干个线程对象并行进行资源的访问时实现的资源处理保护操作: 线程死锁概念:是指两个线程都在等待对方先完成,造 ...
- java多线程系列(五)---synchronized ReentrantLock volatile Atomic 原理分析
java多线程系列(五)---synchronized ReentrantLock volatile Atomic 原理分析 前言:如有不正确的地方,还望指正. 目录 认识cpu.核心与线程 java ...
- Java多线程6:Synchronized锁代码块(this和任意对象)
一.Synchronized(this)锁代码块 用关键字synchronized修饰方法在有些情况下是有弊端的,若是执行该方法所需的时间比较长,线程1执行该方法的时候,线程2就必须等待.这种情况下就 ...
- Java多线程的同步控制记录
Java多线程的同步控制记录 一.重入锁 重入锁完全可以代替 synchronized 关键字.在JDK 1.5 早期版本,重入锁的性能优于 synchronized.JDK 1.6 开始,对于 sy ...
- Java多线程之同步集合和并发集合
Java多线程之同步集合和并发集合 不管是同步集合还是并发集合他们都支持线程安全,他们之间主要的区别体现在性能和可扩展性,还有他们如何实现的线程安全. 同步集合类 Hashtable Vector 同 ...
- Java多线程的同步机制(synchronized)
一段synchronized的代码被一个线程执行之前,他要先拿到执行这段代码的权限,在 java里边就是拿到某个同步对象的锁(一个对象只有一把锁): 如果这个时候同步对象的锁被其他线程拿走了,他(这个 ...
- Java多线程简析——Synchronized(同步锁)、Lock以及线程池
Java多线程 Java中,可运行的程序都是有一个或多个进程组成.进程则是由多个线程组成的.最简单的一个进程,会包括mian线程以及GC线程. 线程的状态 线程状态由以下一张网上图片来说明: 在图中, ...
- Java多线程之二(Synchronized)
常用API method 注释 run() run()方法是我们创建线程时必须要实现的方法,但是实际上该方法只是一个普通方法,直接调用并没有开启线程的作用. start() start()方法作用为使 ...
随机推荐
- 第一次scrum meeting
在这次会议中,我们确定了任务的具体分配.这里截取一部分,每个人都有20个小时左右的编程任务,整个项目共计约140小时. 明天是正式开始软件实现的第一天,下面列出前两天每个人的任务: 第一天 第二天 ...
- 第二个Spring冲刺周期团队进展报告
第一天:找识别不了的原因 第二天:继续找识别不了的原因 第三天:找文字库,找到tessdata语言包,放到手机SD卡根目录 第四天:了解OCR引擎 第五天:将导入tess-two导入到项目中,并进行测 ...
- Mininet安装
Mininet 安装 根据SDNLAB上的实验进行安装.连接地址 需要注意的是切换到用户目录下进行clone github上的源码. 1.卸载之前安装的Mininet 最好是先到目录下看是否有这些文件 ...
- 11th 5个新的问题——关于软件工程
5个新的问题: 1.现在课上,我们每一个团队开发一个软件,遵循的是敏捷流程,近乎每天都召开Scrum会议,但这一切都基于团队人数很少,这样我们可以畅所欲言,而且不会花费过长时间,但是,如果是大团队呢? ...
- formidable模块的使用
Node.js的Formidable模块的使用 今天总结了下Node.js的Formidable模块的使用,下面做一些简要的说明. 1) 创建Formidable.IncomingForm ...
- Thinkphp中import的几个用法详细介绍
下面附上import的几个用法介绍 1.用法一 import('@.Test.Translate');@,表示项目根目录.假定根目录是:App/导入类库的路径是:App/Lib/Test/Transl ...
- jQuery3 slim版本和普通版本区别,如何选择?
区别概述: slim即简化版,比普通版本缺少Ajax和特效模块模块. 官方发布地址:http://blog.jquery.com/2017/03/20/jquery-3-2-1-now-availab ...
- MySQL : 数据库和表的基本操作总结
针对database和table的操作大致可分为三类:创建,查询,修改,删除 1. 创建 create ①创建数据库 create database db_name; ②创建表 create tabl ...
- java学习之switch 等值判断
当匹配到相等的值时候 则进入case里面执行语句 当该语句有break时候 则退出匹配 当没有break时候 则继续往下匹配 直到遇到break才停止匹配
- 【codeforces666E】Forensic Examination 广义后缀自动机+树上倍增+线段树合并
题目描述 给出 $S$ 串和 $m$ 个 $T_i$ 串,$q$ 次询问,每次询问给出 $l$ .$r$ .$x$ .$y$ ,求 $S_{x...y}$ 在 $T_l,T_{l+1},...,T_r ...