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

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

  • 相关阅读:
    Anagram
    HDU 1205 吃糖果(鸽巢原理)
    Codeforces 1243D 0-1 MST(补图的连通图数量)
    Codeforces 1243C Tile Painting(素数)
    Codeforces 1243B2 Character Swap (Hard Version)
    Codeforces 1243B1 Character Swap (Easy Version)
    Codeforces 1243A Maximum Square
    Codeforces 1272E Nearest Opposite Parity(BFS)
    Codeforces 1272D Remove One Element
    Codeforces 1272C Yet Another Broken Keyboard
  • 原文地址:https://www.cnblogs.com/newwind/p/8953491.html
Copyright © 2011-2022 走看看