生产者消费者问题

【转】分布式之消息队列复习精讲

眉间皱痕 提交于 2019-12-03 09:36:13
转自: https://www.cnblogs.com/rjzheng/p/8994962.html 引言 为什么写这篇文章? 博主有两位朋友分别是小A和小B: 小A,工作于传统软件行业(某社保局的软件外包公司),每天工作内容就是和产品聊聊需求,改改业务逻辑。再不然就是和运营聊聊天,写几个SQL,生成下报表。又或者接到客服的通知,某某功能故障了,改改数据,然后下班部署上线。每天过的都是这种生活,技术零成长。 小B,工作于某国企,虽然能接触到一些中间件技术。然而,他只会订阅/发布消息。通俗点说,就是调调API。对为什么使用这些中间件啊?如何保证高可用啊?没有充分的认识。 庆幸的是两位朋友都很有上进心,于是博主写这篇文章,帮助他们复习一下关于消息队列中间件这块的要点 复习要点 本文大概围绕如下几点进行阐述: 为什么使用消息队列? 使用消息队列有什么缺点? 消息队列如何选型? 如何保证消息队列是高可用的? 如何保证消息不被重复消费? 如何保证消费的可靠性传输? 如何保证消息的顺序性? 我们围绕以上七点进行阐述。需要说明一下,本文不是《消息队列从入门到精通》这种课程,因此只是提供一个复习思路,而不是去教你们怎么调用消息队列的API。建议对消息队列不了解的人,去找点消息队列的博客看看,再看本文,收获更大 正文 1、为什么要使用消息队列? 分析 :一个用消息队列的人,不知道为啥用,这就有点尴尬

信号量及一个简单的生产者消费者应用

你离开我真会死。 提交于 2019-12-03 04:39:54
信号量的使用是用来保护共享资源,使得资源在一个时刻只有一个进程(线程)所拥有。当信号量的值为正的时候,说明它空闲, 所测试的线程可以锁定而使用它。若为 0 , 说明它被占用,测试的线程要进入睡眠队列中,等待被唤醒。 信号量分为有名信号量和无名信号量。 有名信号量,其值保存在文件中,可以用来进程间的同步。无名信号量,其值保存在内存中,主要用来线程间同步。 有名信号量的创建: #include <semaphore.h> sem_t *sem_open(const char *name, int oflag, ... /* mode_t mode, unsigned int value */ ); 返回值:若成功则返回指向信号量的指针,若出错则返回SEM_FAILED 如果使用一个现存的有名信号量,我们只需指定两个参数:信号量名和oflag (oflag 取0 )。把oflag 设置为O_CREAT 标志时,如果指定的信号量不存在则新建一个有名信号量;如果指定的信号量已经存在,那么打开使用,无其他额外操作发生 如果我们想要确保我们在创建一个新的信号量,可以把oflag 参数设置为:O_CREAT|O_EXCL 。如果信号量已经存在的话,这会导致sem_open 调用失败。 无名信号量的创建: 信号量的函数都以sem_ 开头,线程中使用的基本信号函数有4 个

C# 生产者与消费者模式

匿名 (未验证) 提交于 2019-12-02 23:57:01
情景:一个线程不断获取数据,另一个线程不断处理这些数据。 常规方法:数据列表加锁,两个线程获取锁,拿到操作权;类似代码如下:(不推荐) static void Main ( string [] args ) { lockClass l = new lockClass (); for ( int i = 0 ; i < 1000000 ; i ++) { l . Equeue ( i . ToString ()); } } public class lockClass { Queue <string> currentQueue = new Queue <string> ( 10000000 ); //当前要插入数据的队列 static readonly object objlock = new object (); FileStream f = new FileStream ( "D://1.txt" , FileMode . Create , FileAccess . Write , FileShare . None ); StreamWriter writer ; public lockClass () { writer = new StreamWriter ( f ); var backgroundWorker = new BackgroundWorker ();

使用BlockingQueue(阻塞队列)及多线程实现数据发送实例详解

匿名 (未验证) 提交于 2019-12-02 22:56:40
一、 BlockingQueue简介 ? 阻塞队列 BlockingQueue 顾名思义是一个队列,在多线程环境中可以通过队列非常方便的实现数据共享。比如常规的“生产者”、“消费者”模型中,常常会出现生产者、消费者数据处理速度不匹配的情况,当生产者产生数据速度过快,那么必须阻塞生产者线程,以便等待消费者线程把累积的数据处理完毕。在多线程环境下,程序员自己控制这些细节显得十分复杂,尤其还要兼顾效率和线程安全,使用 BlockingQueue 就简化了这个问题。不需要再关心什么时候需要阻塞线程,什么时候需要唤醒线程了。 二 、开发实例 下面代码是在spring框架下使用BlockingQueue实现短信发送功能 @Service public class NotifyQueueService { @Autowired NotifyService notifyService; private static BlockingQueue<Runnable> runnableQueue; private static BlockingQueue<NotifyMsg> notifyQueue; private static ThreadPoolExecutor threadPoolExecutor; private static Thread noticThread; /*项目启动时初始化线程池

Python并发编程之多进程

匿名 (未验证) 提交于 2019-12-02 22:51:30
进程:正在进行的一个过程或者说一个任务。而负责执行任务则是cpu。 进程是资源分配的基本单位 进程有:代码段,数据段,进程控制块(PCB)组成 程序仅仅只是一堆代码而已,而进程指的是程序的运行过程。 举例: 想象一位有一手好厨艺的计算机科学家正在为他的女儿烘制生日蛋糕。 他有做生日蛋糕的食谱, 厨房里有所需的原料:面粉、鸡蛋、韭菜,蒜泥等。 在这个比喻中: 做蛋糕的食谱就是程序 (即用适当形式描述的算法) 计算机科学家就是处理器(cpu) 而做蛋糕的各种原料就是输入数据 。 进程就是厨师阅读食谱、取来各种原料以及烘制蛋糕等一系列动作的总和 。 需要强调的是:同一个程序执行两次,那也是两个进程,比如打开暴风影音,虽然都是同一个软件,但是一个可以播放苍井空,一个可以播放饭岛爱。 无论是并行还是并发,在用户看来都是'同时'运行的,不管是进程还是线程,都只是一个任务而已,真是干活的是cpu,cpu来做这些任务,而一个cpu同一时刻只能执行一个任务 并发:在同一个 时间段 内多个任务同时进行,伪并行,即看起来是同时运行。单个cpu+多道技术就可以实现并发(并行也属于并发) 举例: 你是一个cpu,你同时谈了三个女朋友,每一个都可以是一个恋爱任务,你被这三个任务共享,要玩出并发恋爱的效果,应该是你先跟女友1去看电影,看了一会说:不好,我要拉肚子,然后跑去跟第二个女友吃饭,吃了一会说:那啥

Java多线程学习-----wait()、notify/notifyAll()的使用

匿名 (未验证) 提交于 2019-12-02 21:45:52
多线程的几种状态 新建 就绪 运行 阻塞 死亡 新建: 线程被创建出来 就绪: 具有CPU的执行资格, 但是不具有CPU的执行权 运行: 具有CPU的执行资格, 也具有CPU的执行权 阻塞: 不具有CPU的执行资格, 也不具有CPU的执行权 死亡: 不具有CPU的执行资格, 也不具有CPU的执行权 线程的阻塞状态 上一篇有说过sleep可以使线程处于阻塞状态,今天要说的 wait() 方法也可以使线程处于阻塞状态。首先来看一下这两个方法的区别; 共同点: wait()方法和sleep()方法 都可以使线程处于阻塞状态 都可以设置线程的阻塞时间 不同点: wait() 可以设置时间量,也可以不设置。 sleep() 是要必须要设置休眠的时间 wait() 必须先获得锁,一般配合synchronized 关键字使用,即,一般在synchronized 同步代码块里使用 wait()、notify/notifyAll() 方法;sleep()不一定要获得锁。 sleep() 休眠不会释放锁 wait() 一旦等待就会释放锁,让出cpu的执行权,直到当 notify/notifyAll() 被执行时候,才会被唤醒然后继续往下执行 wait() 阻塞状态的唤醒 当线程执行wait()方法时候,会释放当前的锁,然后让出CPU,进入等待状态。 只有当 notify/notifyAll()

网络编程面试题整理(三)

回眸只為那壹抹淺笑 提交于 2019-12-02 10:44:17
1: 什么是并发和并行? 并发是指一个处理器同时处理多个任务。并行是指多个处理器或者是多核的处理器同时处理多个不同的任务。并发是逻辑上的同时发生(simultaneous),而并行是物理上的同时发生。 2: 进程锁和线程锁的作用? 线程锁: 大家都不陌生,主要用来给方法、代码块加锁。当某个方法或者代码块使用锁时,那么在同一时刻至多仅有一个线程在执行该段代码。当有多个线程访问同一对象的加锁方法 / 代码块时,同一时间只有一个线程在执行,其余线程必须要等待当前线程执行完之后才能执行该代码段。 但是,其余线程是可以访问该对象中的非加锁代码块的。    进程锁: 也是为了控制同一操作系统中多个进程访问一个共享资源,只是因为程序的独立性,各个进程是无法控制其他进程对资源的访问的, 但是可以使用本地系统的信号量控制(操作系统基本知识)。 3: 解释什么是异步非阻塞? 首先需要知道什么是同步和异步: 同步和异步 是针对应用程序和内核的交互而言的,同步指的是用户进程触发IO操作并等待或者轮询的去查看IO操作是否就绪,而异步是指用户进程触发IO操作以后便开始做自己的事情,而当IO操作已经完成的时候会得到IO完成的通知。同步方法表明调用一旦开始,调用者必须等待方法执行完成,才能继续执行后续方法。异步方法表明,方法一旦开始,立即返回,调用者无需等待其中方法执行完成,就可以继续执行后续方法

并发编程之进程1

不问归期 提交于 2019-12-02 00:25:19
目录 并发编程之进程 1.队列介绍 基本介绍 2.进程间通信(推荐使用‘队列’) 生产者消费者模型 并发编程之进程 1.队列介绍 基本介绍 队列:先进先出(FIFO) 堆栈:先进后出 使用方法:from multiprocessing import Queue ​ q =Queue (maxsize),实例化出对象q;maxsize是队列中允许最大项数,省略则无大小限制。 主要方法(Queue类中的方法): 1 q.put方法用以插入数据到队列中,put方法还有两个可选参数:blocked和timeout。如果blocked为True(默认值),并且timeout为正值,该方法会阻塞timeout指定的时间,直到该队列有剩余的空间。如果超时,会抛出Queue.Full异常。如果blocked为False,但该Queue已满,会立即抛出Queue.Full异常。 2 q.get方法可以从队列读取并且删除一个元素。同样,get方法有两个可选参数:blocked和timeout。如果blocked为True(默认值),并且timeout为正值,那么在等待时间内没有取到任何元素,会抛出Queue.Empty异常。如果blocked为False,有两种情况存在,如果Queue有一个值可用,则立即返回该值,否则,如果队列为空,则立即抛出Queue.Empty异常. 3 4 q.get

Day 29 进程互斥锁/队列/线程

ε祈祈猫儿з 提交于 2019-12-01 23:42:01
目录 进程互斥锁 队列 概念介绍 方法介绍 子进程发送数据给父进程 生产者消费者模型 线程 进程和线程的区别 线程的特点 开启线程的两种方式 线程对象的属性 线程互斥锁 进程互斥锁 就是将要执行任务的部门代码(只涉及到修改共享数据的代码)变成串行 第一步: 导入multiprocessing模块下的Lock类 第二步: 在 if __name__ = __main__: 方法下调用Lock类 metux = Lock() ,拿到一个对象 第三步: 在子类中需要共享的数据前后加锁: mutex.acquire() , mutex.release() ''' 抢票功能: 1. 查看余票 2. 开始抢票 ''' from multiprocessing import Process, Lock import time import json def search(user): with open('data.txt', 'r', encoding='utf8') as f: dic = json.load(f) print(f'用户{user}查看余票, 还剩{dic.get("ticket_num")}') def buy(user): with open('data.txt', 'r', encoding='utf8') as f: dic = json.load(f) time

并发编程

情到浓时终转凉″ 提交于 2019-12-01 22:55:43
目录 并发编程 互斥锁 : 队列: 生产者与消费者: 并发编程 互斥锁 : 进程数据不共享,但是共享同一套文件系统; 同一个打印终端,是没有问题的,而共享带来的是竞争,竞争带来的结果就是错乱 互斥锁的意思就是互相排斥,如果把多个进程比喻为多个人,互斥锁的工作原理就是多个人都要去争抢同一个资源 互斥锁的原理,就是把并发改成穿行,降低了效率,但保证了数据安全不错乱 from multiprocessing import Process,Lock import os , time def wprk(lock): lock.acquire() #枷锁 print(f'{os.getpid} is running') time.sleep(2) print(f'{os.getpid} is done') lock.release() #开锁 if __name__ == '__main__': lock =Lock() for i in range(3): P = Process(target = work,args=(lock,)) p.start() 并发运行,效率高,但竞争写同一文件,数据写入错乱 加锁处理:由并发变成了串行,牺牲了运行效率,但保证了数据安全 使用join将并发改成穿行,确实能保证数据安全,但问题是连查票操作也变成只能一个一个人去查了