多线程学习-基础( 十一)synchronized关键字修饰方法的简单案例
一、本案例设计到的知识点
(1)Object的notify(),notifyAll(),wait()等方法
(2)Thread的sleep(),interrupt()。
(3)如何终止线程。
(4)如何控制多个线程之间按顺序执行。
二、一个电梯的上下运送人员的案例
引用生活中的一个情景,(先从最简单的处理方式出发,以后再出后续研究版本):
已知:一楼是服务大厅,顶楼是一个餐厅(食堂),顶楼有一群人等待坐电梯下到一楼,一楼有部分人再等待坐电梯去顶楼。限制的条件有:只有一部电梯,每次电梯只能运载一个人。
那么如何实现这种场景呢?
(以后再放开条件研究:多部电梯,多个人,去不同楼层的实现方法,此处先从最简单的入手)
那么继续分析:
把当前的场景按照面向对象的思想来抽象一下:
创建如下类:Personnel 工作人员类,Elevator 电梯类,DownThread 电梯下送工作线程,UpThread 电梯上送工作线程, 以及一个测试类ThreadTest
具体代码如下:
Personnel 工作人员类
package com.jason.models;
/**
* 多线程学习:·分析
* @function 工作人员类
* @author 小风微凉
* @time 2018-4-26 下午1:01:53
*/
public class Personnel {
private String name;
public Personnel(String name){
this.name=name;
}
@Override
public String toString() {
return this.name;
}
}
Elevator 电梯类
package com.jason.models;
import java.util.ArrayList;
import java.util.List;
/**
* 多线程学习:生产者消费者模型·分析
* @function 电梯类
* @author 小风微凉
* @time 2018-4-26 下午1:00:58
*/
public class Elevator{
//电梯编号:以后扩展
private String eleNo;
//电梯每次最大的载重人数为:15人
private final int MAX_PERSON_LIMIT=15;
//构造器
public Elevator(String eleNo){
this.eleNo=eleNo;
}
/**
* //向上运送人员
* @param list 上限运载的人数
* @param exitFlag true 终止线程 false 继续
* @return 返回成功运载的人数
*/
public synchronized void upCarry(List<Personnel> list,boolean exitFlag){
//当前电梯的乘坐人数
int currCount=list.size();
if(currCount==0){//没有人员乘坐
System.out.println("(up)当前电梯没有人员乘坐,可以抢夺电梯的使用权!");
this.notifyAll();//唤醒楼上-楼下的人争抢按电梯
}
if(currCount>MAX_PERSON_LIMIT){//人数超载
System.out.println("(up)警告!人数超过运载上限:"+currCount+","+MAX_PERSON_LIMIT+"人,电梯等候运行!");
try {
Thread.sleep(1000);//带着电梯对象锁,休眠一会
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();//中断线程
}
}
if(currCount>0 && currCount<=MAX_PERSON_LIMIT){//正常运载范围
System.out.println(Thread.currentThread().getName()+":向上运载了第:"+list.size()+"位乘客。抵达楼顶食堂");
this.notifyAll();//只是为了唤醒其他线程,并释放当前线程(和下面wait()有重复)
try {
this.wait();//此时电梯到达楼上,当前线程进入等待池
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();//中断线程
}
System.out.println("---------------[继续UP]后续代码继续执行-------------");
}
if(exitFlag){
//终止当前线程,唤醒其他线程
this.notifyAll();
}
}
/**
* //向下运送人员
* @param list 上限运载的人数
* @return 返回成功运载的人数
*/
public synchronized void downCarry(List<Personnel> list,boolean exitFlag){
//当前电梯的乘坐人数
int currCount=list.size();
if(currCount==0){//没有人员乘坐
System.out.println("(downn)当前电梯没有人员乘坐,可以抢夺电梯的使用权!");
this.notifyAll();//唤醒楼上-楼下的人争抢按电梯
}
if(currCount>MAX_PERSON_LIMIT){//人数超载
System.out.println("(downn)警告!人数超过运载上限:"+currCount+","+MAX_PERSON_LIMIT+"人,电梯等候运行!");
try {
Thread.sleep(1000);//带着电梯对象锁,休眠一会
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();//中断线程
}
}
if(currCount>0 && currCount<=MAX_PERSON_LIMIT){//正常运载范围
System.out.println(Thread.currentThread().getName()+":向下运载了第:"+list.size()+"位乘客。抵达一楼大厅");
this.notifyAll();
try {
this.wait();//此时电梯到达楼下,下送线程进入等待池,上送线程可以拿到电梯使用权
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();//中断线程
}
System.out.println("---------------[继续DOWN]后续代码继续执行-------------");
}
if(exitFlag){
//终止当前线程,唤醒其他线程
this.notifyAll();
}
}
}
UpThread 电梯上送工作线程
/**
* 上送工作线程
* @function
* @author 小风微凉
* @time 2018-4-26 下午1:48:44
*/
class UpThread implements Runnable{
private Elevator elev;
List<Personnel> list;
public UpThread(Elevator elev,List<Personnel> list){
this.elev=elev;
this.list=list;
}
public void run() {
for(int i=1;i<=list.size();i++){
if(i==list.size()){
elev.upCarry(list.subList(0, i),true);
}else{
elev.upCarry(list.subList(0, i), false);
}
}
System.out.println("******[UP线程-END]******************");
}
}
DownThread 电梯下送工作线程
/**
* 下送工作线程
* @function
* @author 小风微凉
* @time 2018-4-26 下午1:48:44
*/
class DownThread implements Runnable{
private Elevator elev;
List<Personnel> list;
public DownThread(Elevator elev,List<Personnel> list){
this.elev=elev;
this.list=list;
}
public void run() {
for(int i=1;i<=list.size();i++){
if(i==list.size()){
elev.downCarry(list.subList(0, i),true);
}else{
elev.downCarry(list.subList(0, i), false);
}
}
System.out.println("******[DOWN线程-END]******************");
}
}
一个测试类ThreadTest
package com.jason.models; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List; public class ThreadTest extends Thread{
/**
* @param args
*/
public static void main(String[] args) {
//假设楼上:20人在等待电梯
List<Personnel> topList=new ArrayList<Personnel>();
for(int i=1;i<=20;i++){
topList.add(new Personnel("TOP"+i+"号"));
}
//假设楼下:30人在等待电梯
List<Personnel> bottomList=new ArrayList<Personnel>();
for(int i=1;i<=30;i++){
bottomList.add(new Personnel("BOTTOM"+i+"号"));
}
//创建电梯对象
Elevator elev=new Elevator("1号电梯");
//2种工作线程,随即运载工作人员
new Thread(new UpThread(elev,topList),"UP").start();
new Thread(new DownThread(elev,bottomList),"DOWN").start();
}
}
运行结果:
UP:向上运载了第:1位乘客。抵达楼顶食堂
DOWN:向下运载了第:1位乘客。抵达一楼大厅
---------------[继续UP]后续代码继续执行-------------
UP:向上运载了第:2位乘客。抵达楼顶食堂
---------------[继续DOWN]后续代码继续执行-------------
DOWN:向下运载了第:2位乘客。抵达一楼大厅
---------------[继续UP]后续代码继续执行-------------
UP:向上运载了第:3位乘客。抵达楼顶食堂
---------------[继续DOWN]后续代码继续执行-------------
DOWN:向下运载了第:3位乘客。抵达一楼大厅
---------------[继续UP]后续代码继续执行-------------
UP:向上运载了第:4位乘客。抵达楼顶食堂
---------------[继续DOWN]后续代码继续执行-------------
DOWN:向下运载了第:4位乘客。抵达一楼大厅
---------------[继续UP]后续代码继续执行-------------
UP:向上运载了第:5位乘客。抵达楼顶食堂
---------------[继续DOWN]后续代码继续执行-------------
DOWN:向下运载了第:5位乘客。抵达一楼大厅
---------------[继续UP]后续代码继续执行-------------
UP:向上运载了第:6位乘客。抵达楼顶食堂
---------------[继续DOWN]后续代码继续执行-------------
DOWN:向下运载了第:6位乘客。抵达一楼大厅
---------------[继续UP]后续代码继续执行-------------
UP:向上运载了第:7位乘客。抵达楼顶食堂
---------------[继续DOWN]后续代码继续执行-------------
DOWN:向下运载了第:7位乘客。抵达一楼大厅
---------------[继续UP]后续代码继续执行-------------
UP:向上运载了第:8位乘客。抵达楼顶食堂
---------------[继续DOWN]后续代码继续执行-------------
DOWN:向下运载了第:8位乘客。抵达一楼大厅
---------------[继续UP]后续代码继续执行-------------
UP:向上运载了第:9位乘客。抵达楼顶食堂
---------------[继续DOWN]后续代码继续执行-------------
DOWN:向下运载了第:9位乘客。抵达一楼大厅
---------------[继续UP]后续代码继续执行-------------
UP:向上运载了第:10位乘客。抵达楼顶食堂
---------------[继续DOWN]后续代码继续执行-------------
DOWN:向下运载了第:10位乘客。抵达一楼大厅
---------------[继续UP]后续代码继续执行-------------
UP:向上运载了第:11位乘客。抵达楼顶食堂
---------------[继续DOWN]后续代码继续执行-------------
DOWN:向下运载了第:11位乘客。抵达一楼大厅
---------------[继续UP]后续代码继续执行-------------
UP:向上运载了第:12位乘客。抵达楼顶食堂
---------------[继续DOWN]后续代码继续执行-------------
DOWN:向下运载了第:12位乘客。抵达一楼大厅
---------------[继续UP]后续代码继续执行-------------
UP:向上运载了第:13位乘客。抵达楼顶食堂
---------------[继续DOWN]后续代码继续执行-------------
DOWN:向下运载了第:13位乘客。抵达一楼大厅
---------------[继续UP]后续代码继续执行-------------
UP:向上运载了第:14位乘客。抵达楼顶食堂
---------------[继续DOWN]后续代码继续执行-------------
DOWN:向下运载了第:14位乘客。抵达一楼大厅
---------------[继续UP]后续代码继续执行-------------
UP:向上运载了第:15位乘客。抵达楼顶食堂
---------------[继续DOWN]后续代码继续执行-------------
DOWN:向下运载了第:15位乘客。抵达一楼大厅
---------------[继续UP]后续代码继续执行-------------
(up)警告!人数超过运载上限:16,15人,电梯等候运行!
(up)警告!人数超过运载上限:17,15人,电梯等候运行!
(up)警告!人数超过运载上限:18,15人,电梯等候运行!
(up)警告!人数超过运载上限:19,15人,电梯等候运行!
(up)警告!人数超过运载上限:20,15人,电梯等候运行!
---------------[继续DOWN]后续代码继续执行-------------
******[UP线程-END]******************
(downn)警告!人数超过运载上限:16,15人,电梯等候运行!
(downn)警告!人数超过运载上限:17,15人,电梯等候运行!
(downn)警告!人数超过运载上限:18,15人,电梯等候运行!
(downn)警告!人数超过运载上限:19,15人,电梯等候运行!
(downn)警告!人数超过运载上限:20,15人,电梯等候运行!
(downn)警告!人数超过运载上限:21,15人,电梯等候运行!
(downn)警告!人数超过运载上限:22,15人,电梯等候运行!
(downn)警告!人数超过运载上限:23,15人,电梯等候运行!
(downn)警告!人数超过运载上限:24,15人,电梯等候运行!
(downn)警告!人数超过运载上限:25,15人,电梯等候运行!
(downn)警告!人数超过运载上限:26,15人,电梯等候运行!
(downn)警告!人数超过运载上限:27,15人,电梯等候运行!
(downn)警告!人数超过运载上限:28,15人,电梯等候运行!
(downn)警告!人数超过运载上限:29,15人,电梯等候运行!
(downn)警告!人数超过运载上限:30,15人,电梯等候运行!
******[DOWN线程-END]******************
运行结果的说明:
(1)程序运行,UP线程和DOWN线程第一时间开始抢夺电梯的使用权。
(2)UP线程和DOWN线程开始按顺序,一次UP,紧接着一次DOWN 交替(等待-唤醒)的轮转。
(3)当其中一个线程结束后,主动唤醒另外一个线程继续执行。
好像逻辑蛮简单的,我酝酿下,再出下一个版本吧~
多线程学习-基础( 十一)synchronized关键字修饰方法的简单案例的更多相关文章
- 【synchronized锁】通过synchronized锁 反编译查看字节码指令分析synchronized关键字修饰方法与代码块的区别
前提: 首先要铺垫几个前置的知识: Java中的锁如sychronize锁是对象锁,Java对象头中具有标识位,当对象锁升级为重量级锁时,重量级锁的标识位会指向监视器monitor, 而每个Java对 ...
- 多线程学习-基础( 九)线程同步Synchronized关键字
一.线程同步1.synchronized关键字的作用域有二种:(1)某个对象实例内:synchronized aMethod(){}可以防止多个线程同时访问这个对象的synchronized方法(如果 ...
- JAVA多线程学习- 三:volatile关键字
Java的volatile关键字在JDK源码中经常出现,但是对它的认识只是停留在共享变量上,今天来谈谈volatile关键字. volatile,从字面上说是易变的.不稳定的,事实上,也确实如此,这个 ...
- Java多线程(三)—— synchronized关键字详解
一.多线程的同步 1.为什么要引入同步机制 在多线程环境中,可能会有两个甚至更多的线程试图同时访问一个有限的资源.必须对这种潜在资源冲突进行预防. 解决方法:在线程使用一个资源时为其加锁即可. 访问资 ...
- Java 多线程(六) synchronized关键字详解
多线程的同步机制对资源进行加锁,使得在同一个时间,只有一个线程可以进行操作,同步用以解决多个线程同时访问时可能出现的问题. 同步机制可以使用synchronized关键字实现. 当synchroniz ...
- 牛客网Java刷题知识点之同步方法和同步代码块的区别(用synchronized关键字修饰)
不多说,直接上干货! 扩展博客 牛客网Java刷题知识点之多线程同步的实现方法有哪些 为何要使用同步? java允许多线程并发控制,当多个线程同时操作一个可共享的资源变量时(如数据的增删改查 ...
- synchronized关键字修饰非静态方法与静态方法的区别
这里我们先创建ObjLock类,并实现Runnable接口.并创建一个Demo类,具有被synchronized关键字修饰的非静态方法与静态方法. 非静态方法 public class ObjLock ...
- 并发编程学习笔记(3)----synchronized关键字以及单例模式与线程安全问题
再说synchronized关键字之前,我们首先先小小的了解一个概念-内置锁. 什么是内置锁? 在java中,每个java对象都可以用作synchronized关键字的锁,这些锁就被称为内置锁,每个对 ...
- [多线程] 线程中的synchronized关键字锁
为什么要用锁? 在多线程中,难免会出现在多个线程中对同一个对象的实例变量或者全局静态变量进行并发访问的情况,如果不做正确的同步处理,那么产生的后果就是"脏读",也就是取到的数据其实 ...
随机推荐
- HAWQ 操作笔记
1.HAWQ 是不支持主键和外建的,官方文档明确给出 Notes Using OIDs in new applications is not recommended. Avoid assuming t ...
- LeetCode Second Minimum Node In a Binary Tree
原题链接在这里:https://leetcode.com/problems/second-minimum-node-in-a-binary-tree/description/ 题目: Given a ...
- [转]express 路由控制--next
next() express的路由控制有个next()功能,在定义了多个路由的时候,对匹配的url会按顺序执行, 例如,有这样两个路由,第一个路由会对满足“/”的地址,在req中添加一个user的属性 ...
- 怎么让eclipse调试的时候不进入 class文件中去
Eclipse -> Window ->Preferences ->Java ->Debug "Suspend execution on uncaught excep ...
- java代码继承。。。找出不能继承父类方法的问题
总结:当子类中没有定义name属性时,在子类的无参构造方法中,父类的姓名是不能被继承的. 输出的结果是,子类无参构造方法里的属性值,也就是是属 控制台显示: 我叫:周杰伦,今年:2岁我的姓名:周杰伦, ...
- DCloud-MUI:HBuilder 安装
ylbtech-DCloud-MUI:HBuilder 安装 1.返回顶部 1. 2. 3. 4. 2.返回顶部 3.返回顶部 4.返回顶部 5.返回顶部 6.返回顶部 7.返 ...
- PostgreSQL 9.5 客户端认证
PostgreSQL 9.5 客户端认证 当一个客户端应用连接一个数据库服务器时,它将指定以哪个PostgreSQL 数据库用户名连接,就像我们以一个特定用户登录一台 Unix 计算机一样.在 SQL ...
- UE4模型导入基础教程
转自:http://www.unrealchina.net/portal.php?mod=view&aid=290
- CS231n 2016 通关 第三章-SVM与Softmax
1===本节课对应视频内容的第三讲,对应PPT是Lecture3 2===本节课的收获 ===熟悉SVM及其多分类问题 ===熟悉softmax分类问题 ===了解优化思想 由上节课即KNN的分析步骤 ...
- java 多线程系列基础篇(一)
多线程状态图: Thread类的两个方法比较: yield方法: Yield是一个静态的原生(native)方法 Yield告诉当前正在执行的线程把运行机会交给线程池中拥有相同优先级的线程. Yiel ...