Java中的多线程之阻塞队列

1.概念

阻塞队列是在普通的(先进先出)队列的基础上,做出了扩充~~(标准库中原有的队列Queue和其子类,默认都是线程不安全的。)

1)线程安全

2)具有阻塞特性

        a)如果队列为空,进行出队列操作,此时就会出现阻塞;一直阻塞到其它线程往队列里添加元素为止。

        b)如果队列为满,进行入队列操作,此时也会出现阻塞;一直阻塞到其它线程从队列里取走元素为止。

2.应用场景

基于阻塞队列,最大的应用场景就是实现“生产者消费者模型”。

案例:包饺子

第一种典型的包法:三个人每个人都分别进行擀饺子皮和包饺子这俩操作~~      但是这种方式其实是比较低效的,这三个人就需要竞争擀面杖,就可能涉及到阻塞等待。

第二种典型的包法:实际生活中大家普遍采取的方案——小明专门负责擀饺子皮,小明媳妇和小明妈妈专门负责包~~   

上述生产者消费者模型在后端开发中经常会涉及到的~~

当下后端开发,常见的结构是“分布式系统”(不是一台服务器解决所有问题,而是分成了多个服务器,服务器之间相互调用~~)。

在上述服务器之间的通信过程中,使用生产者消费者模型就是非常常见的做法~~

使用生产者消费者模型主要有两方面的好处:

1)服务器之间的“解耦合”。(模块之间的关联程度/影响程度,希望见到的是“低耦合”)。

引入生产者消费者模型之后,结构就成了下列模样:

 通常谈到的“阻塞队列”是代码中的一个数据结构。但是由于这个东西太好用了,以致于会把这样的数据结构单独封装成一个服务器程序,并且在单独的服务器机器上进行部署。此时这样的阻塞队列有了一个新的名字——“消息队列”(Message Queue,MQ)。

看起来A、B之间是解耦合了,但是A和队列、B和队列不就又引入了新的耦合吗?

        为啥咱们害怕耦合?耦合的代码在后续变更的过程中比较复杂容易产生bug。消息队列是成熟稳定的产品,代码不会频繁修改即代码是稳定的。A和队列、B和队列之间的交互逻辑基本写一次就固定下来了。

2)通过中间的阻塞队列可以起到“削峰填谷”效果。在遇到请求量激增突发情况下,可以有效保护下游服务器不会被请求冲垮~~

如果是直接调用关系,A收到多少请求,B也会收到多少,很可能直接就把B给搞挂了~~

a)为啥一个服务器收到的请求更多,就可能会挂(可能会崩溃)?

一台服务器就是一台“电脑”,上面就提供了一些硬件资源(包括不限于CPU、内存、硬盘、网络带宽......),就算你这个机器配置再好,硬件资源也是有限的~~服务器每次收到一个请求,处理这个请求的过程,就都需要执行一系列的代码,在执行这些代码过程中,就会需要消耗一定的硬件资源(CPU、内存、硬盘、网络带宽......)。这些请求消耗的总的硬件资源的量超过了机器能提供的上限,那么此时机器就会出现问题(卡死,程序直接崩溃等......)

b)在请求激增的时候,A为啥不会挂?队列为啥不会挂?反而是B更容易挂呢?

A的角色是一个“网关服务器”,收到客户端的请求,再把请求转发给其他的服务器。这样的服务器里面的代码,做的工作比较简单(单纯的数据转发),消耗的硬件资源通常更少。处理一个请求消耗的资源更少,同样的配置下,就能支持更多的请求处理~~同理,队列其实也是比较简单的程序,单位请求消耗的硬件资源也是比较少的。B这个服务器是真正干活的服务器,要真正完成一系列的业务逻辑~~这一系列的工作,代码量非常庞大,消耗的时间很多,消耗的系统硬件资源也是更多的~~类似的MySQL这样的数据库处理每个请求的时候,做的工作就是比较多的,消耗的硬件资源也是比较多的,因此MySQL也是后端系统中容易挂的部分。对应的像Redis这种内存数据库,处理请求做的工作远远少于MySQL做的工作,消耗的资源更少,Redis就比MySQL皮实很多,不容易挂~~

生产者消费者模型的好处:1.解耦合       2.削峰填谷 

生产者消费者模型的代价:1.需要更多的机器来部署这样消息队列(机器/硬件不值钱)   2.A和B之间通信的延时会变长(对于A和B之间的调用,如果要求响应时间比较短,不太适合了~~比较适合转账)

3.标准库中的阻塞队列  

Queue的一些操作(offer、poll)在BlockingQueue中同样也能使用(不能阻塞)

BlockingQueue提供了另外两个专属方法,put入队列take出队列(能阻塞)。阻塞队列没有提供“阻塞版本的”获取队首元素的操作。

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值