生产者消费者问题

多线程-生产者消费者(synchronized同步)

我的未来我决定 提交于 2020-03-12 04:58:46
正解博客:https://blog.csdn.net/u011863767/article/details/59731447 永远在循环(loop)里调用 wait 和 notify,不是在 If 语句 现在你知道wait应该永远在被synchronized的背景下和那个被多线程共享的对象上调用,下一个一定要记住的问题就是,你应该永远在while循环,而不是if语句中调用wait。因为线程是在某些条件下等待的——在我们的例子里,即“如果缓冲区队列是满的话,那么生产者线程应该等待”,你可能直觉就会写一个if语句。但if语句存在一些微妙的小问题,导致即使条件没被满足,你的线程你也有可能被错误地唤醒。所以如果你不在线程被唤醒后再次使用while循环检查唤醒条件是否被满足,你的程序就有可能会出错——例如在缓冲区为满的时候生产者继续生成数据,或者缓冲区为空的时候消费者开始小号数据。所以记住, 永远在while循环而不是if语句中使用wait!我会推荐阅读《 Effective Java 》,这是关于如何正确使用wait和notify的最好的参考资料。 有的这样说:(http://www.tuicool.com/articles/a6ram23) 因为在多核处理器环境中, Signal 唤醒操作可能会激活多于一个线程(阻塞在条件变量上的线程),使得多个调用等待的线程返回

RabbitMQ学习笔记

筅森魡賤 提交于 2020-03-09 18:44:30
1. 消息中间件的核心设计思想 : 采用 异步 通讯、自动 补偿与重试 、 分布式事务 、解决 流量削峰 问题、系统的 解耦 2. 消息中间件常用名词 : Broker 消息转发端,消息中间件Server端; Message 发送的消息内容 roducer 生产者,向Server端投递消息; Consumer 消费者,向Server端获取消息 MessageId 消息全局id 解决消息幂等性问题 3. 主流的MQ对比分析 ActiveMQ: 基本淘汰(老项目使用) 够轻巧(源代码比RocketMQ多),支持持久化到数据库, 对队列数较多的情况支持不好。 RabbitMQ: 结合erlang语言本身的并发优势,支持很多的协议:AMQP,XMPP, SMTP, STOMP, 也正是如此,使的它变的非常重量级,更适合于企业级的开发。 RocketMQ: 阿里系下开源的一款分布式、队列模型的消息中间件,原名Metaq,3.0版本名称改为RocketMQ, 是阿里参照kafka设计思想使用java实现的一套mq,同时将阿里系内部多款mq产品 (Notify、metaq)进行整合,只维护核心功能,去除了所有其他运行时依赖, 保证核心功能最简化,在此基础上配合阿里上述其他开源产品实现不同场景下mq的架构, 目前主要多用于订单交易系统。 Kafka: Apache下的一个子项目

经典同步问题之生产者消费者问题

拥有回忆 提交于 2020-03-09 18:18:58
本文来自个人博客: https://dunkwan.cn 文章目录 Classic Problem of Synchronization(经典同步问题) The Bounded-Buffer Problem(有限缓冲问题) The Producer-Consumer Problem(生产者消费者问题) The Buffer The Producer and Consumer Threads Pthreads Thread Creation and Synchronization Classic Problem of Synchronization(经典同步问题) 在这个部分,我们要讲述大量同步问题,像一大类并发控制问题的例子。对于测试几乎每一个最新提出的同步主题,这些问题都有被用到。在我们的这类问题的解决方案中,因为同步信号量是一种解决该问题的传统方式,所以我们使用同步信号量。然而,这些解决方案的具体实现可能在二元信号量的地方使用互斥锁。 while ( true ) { . . . /* produce an item an next_produced */ . . . wait ( empty ) ; wait ( mutex ) ; . . . /* add next_produced to the buffer */ . . . signal ( mutex ) ;

生产者和消费者问题

≯℡__Kan透↙ 提交于 2020-03-06 09:01:15
public class ProducerConsumer{ public static void main(String[] args){ SyncStack ss = new SyncStack(); Producer p = new Producer(ss); Consumer c = new Consumer(ss); Thread t1 = new Thread(p); Thread t2 = new Thread(c); t1.start(); t2.start(); } } class WoTou{ int id; WoTou(int id){ this.id = id; } public String toString(){ return "WoTou:" + id; } } class SyncStack{ int index = 0; WoTou[] arrayWT = new WoTou[8]; public synchronized void push(WoTou wt){ while(index == arrayWT.length){ try{ this.wait(); } catch(InterruptedException e){ e.printStackTrace(); } } this.notify(); arrayWT[index] = wt;

Python--线程队列(queue)、multiprocessing模块(进程对列Queue、管道(pipe)、进程池)、协程

那年仲夏 提交于 2020-03-05 00:36:02
队列(queue) 队列只在多线程里有意义,是一种线程安全的数据结构。 get与put方法 ''' 创建一个“队列”对象 import queue q = queue.Queue(maxsize = 10) queue.Queue类即是一个队列的同步实现。队列长度可为无限或者有限。可通过Queue的构造函数的可选参数maxsize来设定队列长度。如果maxsize小于1就表示队列长度无限。 将一个值放入队列中: q.put() 调用队列对象的put()方法在队尾插入一个项目。put()有两个参数,第一个item为必需的,为插入项目的值;第二个block为可选参数,默认为True。如果队列当前为空且block为True,put()方法就使调用线程暂停,直到空出一个数据单元。如果block为False,put方法将引发Full异常。 import queue q=queue.Queue(3) q.put(11) q.put(22) q.put(33) q.put(44,False) #queue.Full ==q.put_nowait() 将一个值从队列中取出 q.get() 调用队列对象的get()方法从队头删除并返回一个项目。可选参数为block,默认为True。如果队列为空且block为True,get()就使调用线程暂停,直至有项目可用。如果队列为空且block为False

生产者消费者的几种写法

感情迁移 提交于 2020-03-02 00:50:39
我自己根据理解写了4种,可能会存在问题,望指正! 问题描述: 开5个线程,作为生产者线程,每个线程往容器里放3个; 开5个消费者线程,每个线程从容器里get3次; 如果容器满了,生产者阻塞; 如果容器空了,消费者阻塞。 1.用一个普通的数据结构如ArrayList来实现。 利用synchronized和Object自带的wait()/notifyAll()方法实现。 public static void main(String[] args) { List<Integer> c=new ArrayList<Integer>(5); //producer for(int i=0;i<5;i++) { new Thread(()->{ for(int j=0;j<3;j++) { while(true) { synchronized(c) { if(c.size()<5) { c.add(j); System.out.println(Thread.currentThread().getName()+"product "+j); c.notifyAll(); break; }else { try { c.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } } },String.valueOf(i)

Java多线程-工具篇-BlockingQueue

China☆狼群 提交于 2020-03-01 01:45:07
前言: 在新增的Concurrent包中,BlockingQueue很好的解决了多线程中,如何高效安全“传输”数据的问题。通过这些高效并且线程安全的队列类,为我们快速搭建高质量的多线程程序带来极大的便利。本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景。 认识BlockingQueue 阻塞队列,顾名思义,首先它是一个队列,而一个队列在数据结构中所起的作用大致如下图所示: 从上图我们可以很清楚看到,通过一个共享的队列,可以使得数据由队列的一端输入,从另外一端输出; 常用的队列主要有以下两种:(当然通过不同的实现方式,还可以延伸出很多不同类型的队列,DelayQueue就是其中的一种)   先进先出(FIFO):先插入的队列的元素也最先出队列,类似于排队的功能。从某种程度上来说这种队列也体现了一种公平性。   后进先出(LIFO):后插入队列的元素最先出队列,这种队列优先处理最近发生的事件。 多线程环境中,通过队列可以很容易实现数据共享,比如经典的“生产者”和“消费者”模型中,通过队列可以很便利地实现两者之间的数据共享。假设我们有若干生产者线程,另外又有若干个消费者线程。如果生产者线程需要把准备好的数据共享给消费者线程,利用队列的方式来传递数据,就可以很方便地解决他们之间的数据共享问题。但如果生产者和消费者在某个时间段内

python 队列,进程中的队列,管道,数据共享,进程池部分

风格不统一 提交于 2020-02-28 17:50:39
进程之间的通信:   队列 重要   管道 队列的底层 进程之间的数据共享 进程池 进程间的通信: IPC 队列:先进先出FIFO - 维护秩序的时候用的较多 买票 秒杀 from queue import Queue q = Queue(5) print(q.qsize()) q.put(12) # q.put(3) # q.put(4) # q.put(4) # q.put(4) q.put_nowwait()#当队列满的时候添加会报错,需要使用try print('***',q.qsize()) print(q.get()) # print(q.get()) # print(q.get()) # print(q.get()) #没有值的时候会阻塞 print(q.get_nowwait())#当有值的时候取值 print(q.get_nowait())#当没有值的时候会报错 print(q.full())#查看队列是否满了,常和not使用做判断,要使用try print(q.empty())#查看队列是否是空,常和not使用做判断 print(q.qsize()) #查看队列有几个元素 print(q.get()) print(q.get()) print(q.qsize()) 栈: 先进后出 -- 算法 三级菜单 计算文件的大小 创建共享的进程队列

java之多线程

旧城冷巷雨未停 提交于 2020-02-25 22:23:52
前言:本章主要记载java多线程知识的一些沉淀~ 一、线程的基础知识 1、线程和进程的区别: 进程:系统中一个执行的程序,可称为进程,进程中可以有多个执行的任务(多个顺利执行流)也就是一个线程 一个程序中至少有一个进程,一个进程可包含多个线程,但至少要有一个线程 2、进程的有哪些特性: 独立性:每个进程都是独立存在的实体,拥有自己独立的资源,在没有经过进程本身运行的情况下,其他线程不可以直接访问进程的地址空间 动态性:进程是一个在系统中获得的指令集合,进程加入了时间概念,拥有自己的生命周期和不同的状态,具有动态性 并发性:多个进程可以在多个处理器上并发执行,且进程直接互不影响 敲黑板:并发和并行的区别是什么呢? 并行:同一时间发布多条指令, 不同的处理器上进行运作 并发:同一时刻只发布一条指令 ,通过一些特定的指令,进行轮换执行,从而达到同时执行的效果 并发和并行看似相同,但是确实俩个不同的概念 3、面试经常会问到使用多线程有哪些优势,以及为什么要使用多线程? 先说后者,单线程的功能是非常有限的,随着项目的功能延伸和需求量的增加,单线程很难满足所有的用户需求 举个栗子: 单线程好比餐厅只有一个服务员,他只能做完第一件事才能做第二件事 多线程就像是餐厅有多个服务员,他们各干各的事情,互不打扰 优势:1、进程直接不能共享内存,线程之间可以共享    2

生产者消费者模式中条件判断是使用while而不是if

一世执手 提交于 2020-02-25 11:46:54
永远在循环(loop)里调用 wait 和 notify,不是在 If 语句现在你知道wait应该永远在被synchronized的背景下和那个被多线程共享的对象上调用,下一个一定要记住的问题就是,你应该永远在while循环,而不是if语句中调用wait。因为线程是在某些条件下等待的——在我们的例子里,即“如果缓冲区队列是满的话,那么生产者线程应该等待”,你可能直觉就会写一个if语句。但if语句存在一些微妙的小问题,导致即使条件没被满足,你的线程你也有可能被错误地唤醒。所以如果你不在线程被唤醒后再次使用while循环检查唤醒条件是否被满足,你的程序就有可能会出错——例如在缓冲区为满的时候生产者继续生产数据,或者缓冲区为空的时候消费者开始消耗数据。所以记住, 永远在while循环而不是if语句中使用wait! 因为在多核处理器环境中,Signal唤醒操作可能会激活多于一个线程(阻塞在条件变量上的线程),使得多个调用等待的线程返回。所以用while循环对condition多次判断,可以避免这种假唤醒。 基于以上认知,下面这个是使用wait和notify函数的规范代码模板: // The standard idiom for calling the wait method in Java synchronized(sharedObject) { while(condition) {