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

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

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 }

测试结果

  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

时间: 2024-12-19 16:56:47

多线程访问共同资源(队列,多线程,锁机制)的相关文章

多线程学习之多线程访问共同资源(队列,多线程,锁机制)实例

模拟场景:main方法为网络请求线程(也叫生产者线程),在网络请求线程中开启四个线程(消费者线程),进行高效处理队列中的共同资源(生产者线程生产的共同资源),等待资源处理完毕,网络请求线程执行结束,响应客户端. 消费者线程体 1 /** 2 * 3 */ 4 package com.benxq.Queue; 5 6 import java.text.SimpleDateFormat; 7 import java.util.Date; 8 import java.util.concurrent.B

多节点,多线程下发订单,使用zookeeper分布式锁机制保证订单正确接入oms系统

假设订单下发, 采用单机每分钟从订单OrderEntry接口表中抓100单, 接入订单oms系统中. 由于双十一期间, 订单量激增, 导致订单单机每分钟100单造成, 订单积压. 所以采用多节点多线程处理三方商家的订单接入系统. 流程图: 如图所示: 采用多节点, 多线程, 使用curator操作zk的方式实现, 订单的下发. 以前的方式每分钟下发100单, 之后采用现在的方式可以每分钟2000单, 大大增加系统的订单下发的处理速度, 系统的吞吐量, 提高了效率. 1 操作zookeeper的工

python3.4多线程实现同步的四种方式(锁机制、条件变量、信号量和同步队列)

临界资源即那些一次只能被一个线程访问的资源,典型例子就是打印机,它一次只能被一个程序用来执行打印功能,因为不能多个线程同时操作,而访问这部分资源的代码通常称之为临界区. threading的Lock类,用该类的acquire函数进行加锁,用realease函数进行解锁 import threading import time class Num: def __init__(self): self.num = 0 self.lock = threading.Lock() def add(self)

多线程下的资源同步访问

在一个应用程序中使用多线程 好处是每一个线程异步地执行. 对于Winform程序,可以在后台执行耗时操作的同时,保持前台UI正常地响应用户操作. 对于Service.对于客户端的每一个请求,可以使用一个单独的线程来进行处理.而不是等到前一个用户的请求被完全处理完毕后,才能接着处理下一个用户的请求. 同时,异步带来的问题是,必须协调对资源(文件,网络,磁盘)的访问. 否则,会造成在同一时间两个以上的线程访问同一资源,并且这些线程间相互未知,导致不可预测的数据问题. Lock/Monitor:防止线

python 多线程锁机制

GIL(全局解释器锁) GIL并不是Python的特性,它是在实现Python解析器(CPython)时所引入的一个概念,是为了实现不同线程对共享资源访问的互斥,才引入了GIL 在Cpython解释器中,同一个进程下开启的多线程,同一时刻只能有一个线程执行,无法利用多核优势 python对于计算密集型的任务开多线程的效率甚至不如串行(没有大量切换),但是,对于IO密集型的任务效率还是有显著提升的. GIL原理图 计算密集型:结果肯定是100,因为每一次start结果就已经出来了,所以第二个线程肯

[java多线程] - 锁机制&amp;同步代码块&amp;信号量

在美眉图片下载demo中,我们可以看到多个线程在公用一些变量,这个时候难免会发生冲突.冲突并不可怕,可怕的是当多线程的情况下,你没法控制冲突.按照我的理解在java中实现同步的方式分为三种,分别是:同步代码块机制,锁机制,信号量机制. 一.同步代码块 在java的多线程并发开发过程中,我们最常用的方式就是使用同步代码关键字(synchronized).这种方式的使用不是特别复杂,需要注意的只是你需要明确到底同步的是那个对象,只有当同步的对象一致的情况下,才能够控制互斥的操作.一般情况下,我们会同

Java多线程(二) 多线程的锁机制

当两条线程同时访问一个类的时候,可能会带来一些问题.并发线程重入可能会带来内存泄漏.程序不可控等等.不管是线程间的通讯还是线程共享数据都需要使用Java的锁机制控制并发代码产生的问题.本篇总结主要著名Java的锁机制,阐述多线程下如何使用锁机制进行并发线程沟通. 1.并发下的程序异常 先看下下面两个代码,查看异常内容. 异常1:单例模式 1 package com.scl.thread; 2 3 public class SingletonException 4 { 5 public stati

多线程之锁机制

前言 在Java并发编程实战,会经常遇到多个线程访问同一个资源的情况,这个时候就需要维护数据的一致性,否则会出现各种数据错误,其中一种同步方式就是利用Synchronized关键字执行锁机制,锁机制是先给共享资源上锁,只有拿到锁的线程才可以访问共享资源,其他线程进入等待状态.下面将以实例代码讲解一下 一.wait().nofity().nofityAll()讲解 示例代码 package thread; import java.text.SimpleDateFormat; import java

【转载】5天不再惧怕多线程——第二天 锁机制

当多个线程在并发的时候,难免会碰到相互冲突的事情,比如最经典的ATM机的问题,并发不可怕,可怕的是我们没有能力控制. 线程以我的理解可以分为三种 ① 锁. ② 互斥. ③ 信号. 好,这一篇主要整理"锁",C#提供了2种手工控制的锁 一:  Monitor类 这个算是实现锁机制的纯正类,在锁定的临界区中只允许让一个线程访问,其他线程排队等待.主要整理为2组方法. 1:Monitor.Enter和Monitor.Exit 微软很照护我们,给了我们语法糖Lock,对的,语言糖确实减少了我们