多线程学习-基础( 十一)synchronized关键字修饰方法的简单案例

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

  (1)Object的notify(),notifyAll(),wait()等方法

  (2)Thread的sleep(),interrupt()。

  (3)如何终止线程。

  (4)如何控制多个线程之间按顺序执行。

二、一个电梯的上下运送人员的案例

     引用生活中的一个情景,(先从最简单的处理方式出发,以后再出后续研究版本):

    已知:一楼是服务大厅,顶楼是一个餐厅(食堂),顶楼有一群人等待坐电梯下到一楼,一楼有部分人再等待坐电梯去顶楼。限制的条件有:只有一部电梯,每次电梯只能运载一个人。

    那么如何实现这种场景呢?

    (以后再放开条件研究:多部电梯,多个人,去不同楼层的实现方法,此处先从最简单的入手)  

   那么继续分析:

      把当前的场景按照面向对象的思想来抽象一下:

      创建如下类:Personnel 工作人员类,Elevator  电梯类,DownThread  电梯下送工作线程,UpThread 电梯上送工作线程, 以及一个测试类ThreadTest

  具体代码如下:

  Personnel 工作人员类  

 1 package com.jason.models;
 2 /**
 3  * 多线程学习:·分析
 4  * @function  工作人员类
 5  * @author 小风微凉
 6  * @time  2018-4-26 下午1:01:53
 7  */
 8 public class Personnel {
 9     private String name;
10     public Personnel(String name){
11         this.name=name;
12     }
13     @Override
14     public String toString() {
15         return this.name;
16     }
17 }

 Elevator  电梯类

 1 package com.jason.models;
 2 import java.util.ArrayList;
 3 import java.util.List;
 4 /**
 5  * 多线程学习:生产者消费者模型·分析
 6  * @function  电梯类
 7  * @author 小风微凉
 8  * @time  2018-4-26 下午1:00:58
 9  */
10 public class Elevator{
11     //电梯编号:以后扩展
12     private String eleNo;
13     //电梯每次最大的载重人数为:15人
14     private final int MAX_PERSON_LIMIT=15;
15     //构造器
16     public Elevator(String eleNo){
17         this.eleNo=eleNo;
18     }
19     /**
20      * //向上运送人员
21      * @param list  上限运载的人数
22      * @param exitFlag  true  终止线程   false 继续
23      * @return 返回成功运载的人数
24      */
25     public synchronized void  upCarry(List<Personnel> list,boolean exitFlag){
26         //当前电梯的乘坐人数
27         int currCount=list.size();
28         if(currCount==0){//没有人员乘坐
29             System.out.println("(up)当前电梯没有人员乘坐,可以抢夺电梯的使用权!");
30             this.notifyAll();//唤醒楼上-楼下的人争抢按电梯
31         }
32         if(currCount>MAX_PERSON_LIMIT){//人数超载
33             System.out.println("(up)警告!人数超过运载上限:"+currCount+","+MAX_PERSON_LIMIT+"人,电梯等候运行!");
34             try {
35                 Thread.sleep(1000);//带着电梯对象锁,休眠一会
36             } catch (InterruptedException e) {
37                 e.printStackTrace();
38                 Thread.currentThread().interrupt();//中断线程
39             }
40         }
41         if(currCount>0 && currCount<=MAX_PERSON_LIMIT){//正常运载范围
42             System.out.println(Thread.currentThread().getName()+":向上运载了第:"+list.size()+"位乘客。抵达楼顶食堂");
43             this.notifyAll();//只是为了唤醒其他线程,并释放当前线程(和下面wait()有重复)
44             try {
45                 this.wait();//此时电梯到达楼上,当前线程进入等待池            
46             } catch (InterruptedException e) {
47                 e.printStackTrace();
48                 Thread.currentThread().interrupt();//中断线程
49             }
50             System.out.println("---------------[继续UP]后续代码继续执行-------------");            
51         }
52         if(exitFlag){
53             //终止当前线程,唤醒其他线程
54             this.notifyAll();
55         }
56     }
57     /**
58      * //向下运送人员
59      * @param list  上限运载的人数
60      * @return 返回成功运载的人数
61      */
62     public synchronized void  downCarry(List<Personnel> list,boolean exitFlag){
63         //当前电梯的乘坐人数
64         int currCount=list.size();
65         if(currCount==0){//没有人员乘坐
66             System.out.println("(downn)当前电梯没有人员乘坐,可以抢夺电梯的使用权!");
67             this.notifyAll();//唤醒楼上-楼下的人争抢按电梯
68         }
69         if(currCount>MAX_PERSON_LIMIT){//人数超载
70             System.out.println("(downn)警告!人数超过运载上限:"+currCount+","+MAX_PERSON_LIMIT+"人,电梯等候运行!");
71             try {
72                 Thread.sleep(1000);//带着电梯对象锁,休眠一会
73             } catch (InterruptedException e) {
74                 e.printStackTrace();
75                 Thread.currentThread().interrupt();//中断线程
76             }
77         }
78         if(currCount>0 && currCount<=MAX_PERSON_LIMIT){//正常运载范围
79             System.out.println(Thread.currentThread().getName()+":向下运载了第:"+list.size()+"位乘客。抵达一楼大厅");
80             this.notifyAll();
81             try {
82                 this.wait();//此时电梯到达楼下,下送线程进入等待池,上送线程可以拿到电梯使用权
83             } catch (InterruptedException e) {
84                 e.printStackTrace();
85                 Thread.currentThread().interrupt();//中断线程
86             }
87             System.out.println("---------------[继续DOWN]后续代码继续执行-------------");
88         }
89         if(exitFlag){
90             //终止当前线程,唤醒其他线程
91             this.notifyAll();
92         }
93     }
94 }

 UpThread 电梯上送工作线程 

 1 /**
 2  * 上送工作线程
 3  * @function  
 4  * @author 小风微凉
 5  * @time  2018-4-26 下午1:48:44
 6  */
 7 class UpThread implements Runnable{
 8     private Elevator elev;
 9     List<Personnel> list;
10     public UpThread(Elevator elev,List<Personnel> list){
11         this.elev=elev;
12         this.list=list;
13     }
14     public void run() {
15         for(int i=1;i<=list.size();i++){    
16             if(i==list.size()){
17                 elev.upCarry(list.subList(0, i),true);
18             }else{
19                 elev.upCarry(list.subList(0, i), false);
20             }
21         }
22         System.out.println("******[UP线程-END]******************");
23     }
24 }

 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 

 1 package com.jason.models;
 2 
 3 import java.util.ArrayList;
 4 import java.util.Arrays;
 5 import java.util.List;
 6 
 7 public class ThreadTest extends Thread{
 8     /**
 9      * @param args
10      */
11     public static void main(String[] args) {
12         //假设楼上:20人在等待电梯
13         List<Personnel> topList=new ArrayList<Personnel>();
14         for(int i=1;i<=20;i++){
15             topList.add(new Personnel("TOP"+i+"号"));
16         }
17         //假设楼下:30人在等待电梯
18         List<Personnel> bottomList=new ArrayList<Personnel>();
19         for(int i=1;i<=30;i++){
20             bottomList.add(new Personnel("BOTTOM"+i+"号"));
21         }
22         //创建电梯对象
23         Elevator elev=new Elevator("1号电梯");
24         //2种工作线程,随即运载工作人员
25         new Thread(new UpThread(elev,topList),"UP").start();
26         new Thread(new DownThread(elev,bottomList),"DOWN").start();
27     }
28 }

 运行结果:

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)当其中一个线程结束后,主动唤醒另外一个线程继续执行。

好像逻辑蛮简单的,我酝酿下,再出下一个版本吧~ 

原文地址:https://www.cnblogs.com/newwind/p/8953491.html