一、本案例设计到的知识点

  (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关键字修饰方法的简单案例的更多相关文章

  1. 【synchronized锁】通过synchronized锁 反编译查看字节码指令分析synchronized关键字修饰方法与代码块的区别

    前提: 首先要铺垫几个前置的知识: Java中的锁如sychronize锁是对象锁,Java对象头中具有标识位,当对象锁升级为重量级锁时,重量级锁的标识位会指向监视器monitor, 而每个Java对 ...

  2. 多线程学习-基础( 九)线程同步Synchronized关键字

    一.线程同步1.synchronized关键字的作用域有二种:(1)某个对象实例内:synchronized aMethod(){}可以防止多个线程同时访问这个对象的synchronized方法(如果 ...

  3. JAVA多线程学习- 三:volatile关键字

    Java的volatile关键字在JDK源码中经常出现,但是对它的认识只是停留在共享变量上,今天来谈谈volatile关键字. volatile,从字面上说是易变的.不稳定的,事实上,也确实如此,这个 ...

  4. Java多线程(三)—— synchronized关键字详解

    一.多线程的同步 1.为什么要引入同步机制 在多线程环境中,可能会有两个甚至更多的线程试图同时访问一个有限的资源.必须对这种潜在资源冲突进行预防. 解决方法:在线程使用一个资源时为其加锁即可. 访问资 ...

  5. Java 多线程(六) synchronized关键字详解

    多线程的同步机制对资源进行加锁,使得在同一个时间,只有一个线程可以进行操作,同步用以解决多个线程同时访问时可能出现的问题. 同步机制可以使用synchronized关键字实现. 当synchroniz ...

  6. 牛客网Java刷题知识点之同步方法和同步代码块的区别(用synchronized关键字修饰)

    不多说,直接上干货! 扩展博客 牛客网Java刷题知识点之多线程同步的实现方法有哪些 为何要使用同步?      java允许多线程并发控制,当多个线程同时操作一个可共享的资源变量时(如数据的增删改查 ...

  7. synchronized关键字修饰非静态方法与静态方法的区别

    这里我们先创建ObjLock类,并实现Runnable接口.并创建一个Demo类,具有被synchronized关键字修饰的非静态方法与静态方法. 非静态方法 public class ObjLock ...

  8. 并发编程学习笔记(3)----synchronized关键字以及单例模式与线程安全问题

    再说synchronized关键字之前,我们首先先小小的了解一个概念-内置锁. 什么是内置锁? 在java中,每个java对象都可以用作synchronized关键字的锁,这些锁就被称为内置锁,每个对 ...

  9. [多线程] 线程中的synchronized关键字锁

    为什么要用锁? 在多线程中,难免会出现在多个线程中对同一个对象的实例变量或者全局静态变量进行并发访问的情况,如果不做正确的同步处理,那么产生的后果就是"脏读",也就是取到的数据其实 ...

随机推荐

  1. UVA - 1606 Amphiphilic Carbon Molecules (计算几何,扫描法)

    平面上给你一些具有黑或白颜色的点,让你设置一个隔板,使得隔板一侧的黑点加上另一侧的白点数最多.隔板上的点可视作任意一侧. 易知一定存在一个隔板穿过两个点且最优,因此可以先固定以一个点为原点,将其他点中 ...

  2. mapreduce-实现单表关联

    //map类 package hadoop3; import java.io.IOException; import org.apache.hadoop.io.LongWritable;import ...

  3. hexo博客相关

    https://www.cnblogs.com/sulishibaobei/p/6428241.html 利用hexo+github+nodejs搭建自我博客的一天 http://www.sulish ...

  4. get方法传递中文数据的时候如何进行转码

    首先,如果是在js端的代码,用window.href进行请求时,需要进行转码 前台jsp中: var param = document.getElementById('param').value;pa ...

  5. java代码swing编程 制作一个单选按钮的Frame

    不善于思考,结果费了时间,也没有效果 下面的框框可以做出来. package com.kk; import javax.swing.JFrame; import javax.swing.JLabel; ...

  6. linux下mysql配置文件my.cnf最详细解释

    MySQL配置文件在Windows下叫my.ini,在MySQL的安装根目录下:在Linux下叫my.cnf,该文件位于/etc/my.cnf. 可以查找下:find / -name my.cnf m ...

  7. Oracle Flushback 学习测试

    Oracle Flushback 学习测试:三思笔记 Flashback恢复 从9i开始,利用oracle查询的多版本一致的特点,实现从回滚段中读取一定时间内在表中操作的数据,被称为 flashbac ...

  8. Rails上传文件

    1.view <%= form_tag({:method =>"post",:controller =>"welcome",:action=& ...

  9. Python No module named pkg_resources

    好记性不如烂笔头. I encountered the same ImportError today while trying to use pip. Somehow the setuptools p ...

  10. paramiko监控 windows服务器 被监控服务器只需要安装openssh服务即可基于wmic完成大部分监控

    #!/usr/bin/python #-*- coding: UTF-8 -*- #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ...