zoukankan      html  css  js  c++  java
  • 多线程学习-基础( 十一)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)当其中一个线程结束后,主动唤醒另外一个线程继续执行。

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

  • 相关阅读:
    程序员修炼之道:从小工到专家
    2020.12.16收获
    2020.12.15收获
    2020.12.14收获
    2020.12.13收获
    Android学习第二天——对Android的简单了解
    Java学习12.18
    考试加分项
    Java学习12.17
    Java建议
  • 原文地址:https://www.cnblogs.com/newwind/p/8953491.html
Copyright © 2011-2022 走看看