zoukankan      html  css  js  c++  java
  • 多线程访问共同资源(队列,多线程,锁机制)

    模拟场景:main方法为网络请求线程(也叫生产者线程),在网络请求线程中开启四个线程(消费者线程),进行高效处理队列中的共同资源(生产者线程生产的共同资源),等待资源处理完毕,网络请求线程执行结束,响应客户端。

    消费者线程的线程体

      1 import java.text.SimpleDateFormat;
      2 import java.util.Date;
      3 import java.util.concurrent.BlockingQueue;
      4 import java.util.concurrent.LinkedBlockingQueue;
      5 import java.util.concurrent.TimeUnit;
      6 
      7 /**
      8  * 【1】实现Runnable接口,重写run方法。
      9  * 【2】run方法内的逻辑代码就是线程体
     10  * 【3】创建线程类的对象
     11  * 【4】创建线程类的代理对象
     12  * 【5】代理对象调用start(),启动线程
     13  * @author it-c-1201
     14  *
     15  */
     16 public class MyThread implements Runnable{
     17     //多线程访问共同资源的队列
     18     private  BlockingQueue<String> a = new LinkedBlockingQueue<String>();
     19     
     20     //队列中共同资源的个数
     21     private Integer count=0;
     22     
     23     //线程锁
     24     private Object object=new Object();
     25     
     26     //生产者生产完成标示<false 未生产完成,true 生产完成>
     27     private boolean flag=false;
     28     
     29     //线程类构造器。
     30     public MyThread(BlockingQueue<String> a){
     31         this.a=a;
     32     }
     33     
     34     //获取线程锁对象
     35     public Object getObjectByLock(){
     36         return this.object;
     37     }
     38     
     39     //标志生产者生产结束
     40     public void setFlag(){
     41         this.flag=true;
     42     }
     43 
     44     //队列数据加一个
     45     public void setCount(){
     46         //当出现队列数据小于1的情况,恢复队列中数据个数为0
     47         if(count<0){
     48             count=0;
     49         }
     50         count++;
     51     }
     52     
     53     //线程体
     54     public void run() {
     55         //消费
     56         while(true){
     57             //获取当前线程名字
     58             String threadName=Thread.currentThread().getName();
     59             
     60             //资源处理完毕&&生产者停止生产,则跳出死循环
     61             if(count==0&&flag){
     62                 break;
     63             }
     64             
     65             
     66             String pollInteger;
     67             try {
     68                 //从队列中获取数据。如果没有数据等待100毫秒,100毫秒后还是无数据,返回null
     69                 pollInteger = a.poll(100, TimeUnit.MILLISECONDS);
     70                 
     71                 //如果取出的数据为空,则暂停本次循环,进行下次循环(后边代码不执行)
     72                 if(pollInteger==null){
     73                     continue;
     74                 }
     75                 
     76                 //如果队列中资源个数为0,则暂停本次循环,进行下次循环
     77                 if(count==0||count<0){
     78                     continue;
     79                 }
     80                 
     81                 //说明从队列中取出数据,队列中数据个数减一
     82                 count--;    
     83                 
     84                 //获取执行时间点
     85                 SimpleDateFormat aDateFormat=new SimpleDateFormat("HH:mm:ss SS");
     86                 Date date=new Date();
     87                 String dateString=aDateFormat.format(date);
     88                 //模拟消费队列中获取的数据
     89                 System.out.println("MyThread.run(-->)"+threadName+"【"+pollInteger+"】  时间: "+dateString);
     90             } catch (InterruptedException e) {
     91                 // TODO Auto-generated catch block
     92                 e.printStackTrace();
     93             }
     94             
     95         }
     96         
     97         //唤醒所有线程
     98         synchronized(object){
     99             //唤醒该锁锁住的所有线程【证明没有数据要处理了,main方法中挂起的线程(模拟的网络请求线程)被唤醒,main方法执行结束】
    100             object.notifyAll();
    101             String tString=Thread.currentThread().getName();
    102             System.out.println("MyThread.run(-->)"+tString+"notfyAll()");
    103         }
    104         
    105     }
    106     
    107     
    108 }
    View Code

    main方法(模拟的网络请求线程)

     1 import java.text.SimpleDateFormat;
     2 import java.util.Date;
     3 import java.util.concurrent.BlockingQueue;
     4 import java.util.concurrent.LinkedBlockingQueue;
     5 
     6 
     7 public class Test {
     8     
     9     //模拟多线程消费的共同资源
    10     private static BlockingQueue<String> a = new LinkedBlockingQueue<String>();
    11     
    12     //模拟的网络请求来要执行的方法
    13     public static void main(String[] args) {
    14         //新建线程对象
    15         MyThread myThread=new MyThread(a);
    16         
    17         
    18         //开启四个消费线程
    19         for(int i=0;i<4;i++){
    20             Thread aThread=new Thread(myThread);
    21             aThread.setName("THREAD"+i);
    22             aThread.start();
    23         }
    24         
    25         //模拟生产线程
    26         try {
    27             for(int i=0;i<100;i++){
    28                     //往队列中加数据
    29                     a.put(i+"sxf");
    30                     //队列中数据个数加1
    31                     myThread.setCount();
    32                 }
    33             } catch (InterruptedException e) {
    34                 // TODO Auto-generated catch block
    35                 e.printStackTrace();
    36             }finally{
    37                 myThread.setFlag();
    38             }
    39                         
    40                 
    41         
    42         //模拟当生产完毕后,网络请求线程也叫生产线程被阻塞
    43         synchronized (myThread.getObjectByLock()) {
    44             try {
    45                 myThread.getObjectByLock().wait();
    46             } catch (InterruptedException e) {
    47                 // TODO Auto-generated catch block
    48                 e.printStackTrace();
    49             }
    50         }
    51         
    52         //模拟网络请求线程被唤醒后,执行完毕,向客户端响应数据
    53         SimpleDateFormat aDateFormat=new SimpleDateFormat("HH:mm:ss SS");
    54         Date date=new Date();
    55         String dateString=aDateFormat.format(date);
    56         System.out.println("Test.main(完成时间:)"+dateString);
    57     }
    58 }
    View Code

     测试结果

      1 MyThread.run(-->)THREAD2【2sxf】  时间: 19:39:06 127
      2 MyThread.run(-->)THREAD3【0sxf】  时间: 19:39:06 127
      3 MyThread.run(-->)THREAD0【1sxf】  时间: 19:39:06 127
      4 MyThread.run(-->)THREAD2【4sxf】  时间: 19:39:06 128
      5 MyThread.run(-->)THREAD0【6sxf】  时间: 19:39:06 128
      6 MyThread.run(-->)THREAD1【3sxf】  时间: 19:39:06 127
      7 MyThread.run(-->)THREAD2【7sxf】  时间: 19:39:06 128
      8 MyThread.run(-->)THREAD0【8sxf】  时间: 19:39:06 128
      9 MyThread.run(-->)THREAD3【5sxf】  时间: 19:39:06 128
     10 MyThread.run(-->)THREAD2【10sxf】  时间: 19:39:06 128
     11 MyThread.run(-->)THREAD3【12sxf】  时间: 19:39:06 129
     12 MyThread.run(-->)THREAD1【9sxf】  时间: 19:39:06 128
     13 MyThread.run(-->)THREAD3【14sxf】  时间: 19:39:06 129
     14 MyThread.run(-->)THREAD1【15sxf】  时间: 19:39:06 129
     15 MyThread.run(-->)THREAD3【16sxf】  时间: 19:39:06 129
     16 MyThread.run(-->)THREAD2【13sxf】  时间: 19:39:06 129
     17 MyThread.run(-->)THREAD0【11sxf】  时间: 19:39:06 129
     18 MyThread.run(-->)THREAD3【18sxf】  时间: 19:39:06 129
     19 MyThread.run(-->)THREAD2【19sxf】  时间: 19:39:06 129
     20 MyThread.run(-->)THREAD0【20sxf】  时间: 19:39:06 129
     21 MyThread.run(-->)THREAD3【21sxf】  时间: 19:39:06 129
     22 MyThread.run(-->)THREAD2【22sxf】  时间: 19:39:06 129
     23 MyThread.run(-->)THREAD1【17sxf】  时间: 19:39:06 129
     24 MyThread.run(-->)THREAD3【24sxf】  时间: 19:39:06 129
     25 MyThread.run(-->)THREAD0【23sxf】  时间: 19:39:06 129
     26 MyThread.run(-->)THREAD2【25sxf】  时间: 19:39:06 129
     27 MyThread.run(-->)THREAD1【26sxf】  时间: 19:39:06 129
     28 MyThread.run(-->)THREAD2【29sxf】  时间: 19:39:06 129
     29 MyThread.run(-->)THREAD0【28sxf】  时间: 19:39:06 129
     30 MyThread.run(-->)THREAD3【27sxf】  时间: 19:39:06 129
     31 MyThread.run(-->)THREAD1【30sxf】  时间: 19:39:06 129
     32 MyThread.run(-->)THREAD2【31sxf】  时间: 19:39:06 130
     33 MyThread.run(-->)THREAD0【32sxf】  时间: 19:39:06 130
     34 MyThread.run(-->)THREAD3【33sxf】  时间: 19:39:06 130
     35 MyThread.run(-->)THREAD1【34sxf】  时间: 19:39:06 130
     36 MyThread.run(-->)THREAD2【35sxf】  时间: 19:39:06 130
     37 MyThread.run(-->)THREAD0【36sxf】  时间: 19:39:06 130
     38 MyThread.run(-->)THREAD3【37sxf】  时间: 19:39:06 130
     39 MyThread.run(-->)THREAD1【38sxf】  时间: 19:39:06 130
     40 MyThread.run(-->)THREAD2【39sxf】  时间: 19:39:06 130
     41 MyThread.run(-->)THREAD0【40sxf】  时间: 19:39:06 130
     42 MyThread.run(-->)THREAD3【41sxf】  时间: 19:39:06 130
     43 MyThread.run(-->)THREAD1【42sxf】  时间: 19:39:06 130
     44 MyThread.run(-->)THREAD2【43sxf】  时间: 19:39:06 130
     45 MyThread.run(-->)THREAD0【44sxf】  时间: 19:39:06 130
     46 MyThread.run(-->)THREAD3【45sxf】  时间: 19:39:06 130
     47 MyThread.run(-->)THREAD1【46sxf】  时间: 19:39:06 130
     48 MyThread.run(-->)THREAD2【47sxf】  时间: 19:39:06 130
     49 MyThread.run(-->)THREAD0【48sxf】  时间: 19:39:06 130
     50 MyThread.run(-->)THREAD3【49sxf】  时间: 19:39:06 130
     51 MyThread.run(-->)THREAD1【50sxf】  时间: 19:39:06 130
     52 MyThread.run(-->)THREAD2【51sxf】  时间: 19:39:06 130
     53 MyThread.run(-->)THREAD0【52sxf】  时间: 19:39:06 130
     54 MyThread.run(-->)THREAD3【53sxf】  时间: 19:39:06 130
     55 MyThread.run(-->)THREAD1【54sxf】  时间: 19:39:06 130
     56 MyThread.run(-->)THREAD2【55sxf】  时间: 19:39:06 130
     57 MyThread.run(-->)THREAD0【56sxf】  时间: 19:39:06 130
     58 MyThread.run(-->)THREAD3【57sxf】  时间: 19:39:06 130
     59 MyThread.run(-->)THREAD1【58sxf】  时间: 19:39:06 130
     60 MyThread.run(-->)THREAD3【61sxf】  时间: 19:39:06 131
     61 MyThread.run(-->)THREAD2【59sxf】  时间: 19:39:06 131
     62 MyThread.run(-->)THREAD0【60sxf】  时间: 19:39:06 131
     63 MyThread.run(-->)THREAD1【62sxf】  时间: 19:39:06 131
     64 MyThread.run(-->)THREAD3【63sxf】  时间: 19:39:06 131
     65 MyThread.run(-->)THREAD0【65sxf】  时间: 19:39:06 131
     66 MyThread.run(-->)THREAD1【66sxf】  时间: 19:39:06 131
     67 MyThread.run(-->)THREAD3【67sxf】  时间: 19:39:06 131
     68 MyThread.run(-->)THREAD0【68sxf】  时间: 19:39:06 131
     69 MyThread.run(-->)THREAD1【69sxf】  时间: 19:39:06 131
     70 MyThread.run(-->)THREAD3【70sxf】  时间: 19:39:06 131
     71 MyThread.run(-->)THREAD2【64sxf】  时间: 19:39:06 131
     72 MyThread.run(-->)THREAD0【71sxf】  时间: 19:39:06 131
     73 MyThread.run(-->)THREAD2【74sxf】  时间: 19:39:06 132
     74 MyThread.run(-->)THREAD3【73sxf】  时间: 19:39:06 131
     75 MyThread.run(-->)THREAD0【75sxf】  时间: 19:39:06 132
     76 MyThread.run(-->)THREAD2【76sxf】  时间: 19:39:06 132
     77 MyThread.run(-->)THREAD0【78sxf】  时间: 19:39:06 132
     78 MyThread.run(-->)THREAD2【79sxf】  时间: 19:39:06 132
     79 MyThread.run(-->)THREAD0【80sxf】  时间: 19:39:06 132
     80 MyThread.run(-->)THREAD2【81sxf】  时间: 19:39:06 132
     81 MyThread.run(-->)THREAD0【82sxf】  时间: 19:39:06 132
     82 MyThread.run(-->)THREAD2【83sxf】  时间: 19:39:06 132
     83 MyThread.run(-->)THREAD0【84sxf】  时间: 19:39:06 132
     84 MyThread.run(-->)THREAD2【85sxf】  时间: 19:39:06 132
     85 MyThread.run(-->)THREAD0【86sxf】  时间: 19:39:06 132
     86 MyThread.run(-->)THREAD2【87sxf】  时间: 19:39:06 132
     87 MyThread.run(-->)THREAD0【88sxf】  时间: 19:39:06 132
     88 MyThread.run(-->)THREAD2【89sxf】  时间: 19:39:06 132
     89 MyThread.run(-->)THREAD0【90sxf】  时间: 19:39:06 132
     90 MyThread.run(-->)THREAD2【91sxf】  时间: 19:39:06 132
     91 MyThread.run(-->)THREAD1【72sxf】  时间: 19:39:06 131
     92 MyThread.run(-->)THREAD0【92sxf】  时间: 19:39:06 133
     93 MyThread.run(-->)THREAD3【77sxf】  时间: 19:39:06 132
     94 MyThread.run(-->)THREAD2【93sxf】  时间: 19:39:06 133
     95 MyThread.run(-->)THREAD0【95sxf】  时间: 19:39:06 133
     96 MyThread.run(-->)THREAD1【94sxf】  时间: 19:39:06 133
     97 MyThread.run(-->)THREAD3【96sxf】  时间: 19:39:06 133
     98 MyThread.run(-->)THREAD0【98sxf】  时间: 19:39:06 133
     99 MyThread.run(-->)THREAD2【97sxf】  时间: 19:39:06 133
    100 MyThread.run(-->)THREAD3notfyAll()
    101 MyThread.run(-->)THREAD2notfyAll()
    102 MyThread.run(-->)THREAD0notfyAll()
    103 MyThread.run(-->)THREAD1【99sxf】  时间: 19:39:06 133
    104 MyThread.run(-->)THREAD1notfyAll()
    105 Test.main(完成时间:)19:39:06 133
    View Code
  • 相关阅读:
    JAVA泛类型(汽车Demo)
    java自定义事件机制分析
    ExtJS自定义事件
    模块化设计进化
    面向服务的SOA架构与服务总线ESB
    数据加密数字签名
    面试题
    一点ExtJS开发的感悟
    学习代理模式
    抽象类与接口
  • 原文地址:https://www.cnblogs.com/shangxiaofei/p/4342596.html
Copyright © 2011-2022 走看看