多线程访问共同资源(队列,多线程,锁机制)

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

模拟场景: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

 

相关文章
|
17天前
|
存储 Java 数据库连接
java多线程之线程通信
java多线程之线程通信
|
2天前
|
安全 算法 Java
JavaSE&多线程&线程池
JavaSE&多线程&线程池
15 7
|
2天前
|
存储 缓存 NoSQL
为什么Redis使用单线程 性能会优于多线程?
在计算机领域,性能一直都是一个关键的话题。无论是应用开发还是系统优化,我们都需要关注如何在有限的资源下,实现最大程度的性能提升。Redis,作为一款高性能的开源内存数据库,因其出色的单线程性能而备受瞩目。那么,为什么Redis使用单线程性能会优于多线程呢?
15 1
|
10天前
|
监控 Java 关系型数据库
JVM工作原理与实战(十三):打破双亲委派机制-线程上下文类加载器
JVM作为Java程序的运行环境,其负责解释和执行字节码,管理内存,确保安全,支持多线程和提供性能监控工具,以及确保程序的跨平台运行。本文主要介绍了打破双亲委派机制的方法、线程上下文类加载器等内容。
14 2
|
20天前
|
安全 Java 调度
深入理解Java中的线程安全与锁机制
【4月更文挑战第6天】 在并发编程领域,Java语言提供了强大的线程支持和同步机制来确保多线程环境下的数据一致性和线程安全性。本文将深入探讨Java中线程安全的概念、常见的线程安全问题以及如何使用不同的锁机制来解决这些问题。我们将从基本的synchronized关键字开始,到显式锁(如ReentrantLock),再到读写锁(ReadWriteLock)的讨论,并结合实例代码来展示它们在实际开发中的应用。通过本文,读者不仅能够理解线程安全的重要性,还能掌握如何有效地在Java中应用各种锁机制以保障程序的稳定运行。
|
24天前
|
安全 Java 容器
Java并发编程:实现高效、线程安全的多线程应用
综上所述,Java并发编程需要注意线程安全、可见性、性能等方面的问题。合理使用线程池、同步机制、并发容器等工具,可以实现高效且线程安全的多线程应用。
14 1
|
28天前
|
存储 缓存 NoSQL
Redis单线程已经很快了6.0引入多线程
Redis单线程已经很快了6.0引入多线程
31 3
|
1月前
|
消息中间件 安全 Linux
线程同步与IPC:单进程多线程环境下的选择与权衡
线程同步与IPC:单进程多线程环境下的选择与权衡
58 0
|
1月前
|
Java 调度 C#
C#学习系列相关之多线程(一)----常用多线程方法总结
C#学习系列相关之多线程(一)----常用多线程方法总结
|
1月前
|
安全 编译器 C#
C#学习相关系列之多线程---lock线程锁的用法
C#学习相关系列之多线程---lock线程锁的用法

相关实验场景

更多