| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> Java知识库 -> 【多线程】单例模式、阻塞队列 -> 正文阅读 |
|
[Java知识库]【多线程】单例模式、阻塞队列 |
目录 1.单例模式
单例模式是一种设计模式,单例模式能保证某个类在程序中只存在唯一一份实例,
而不会创建出多个实例
.
1.1饿汉模式举个例子解释饿汉模式:中午使用了三个菜碟,吃完后,马上把三个碗都洗了。
?在下面程序中使用到的 static。 static 修饰的成员更加准确的说,是“类成员”=>“类属性/类方法”。一个java 程序中,一个类对象只存在一份(JVM保证的),进一步的也就保证了类的 static 成员也是只有一份的。
?上诉代码的针对唯一的实例初始化,比较着急,在类加载阶段,就会直接创建实例(程序中用到这个类,就会立即加载),实例就行下面程序所示 ? ?饿汉模式中 getInstance,仅仅是读取了变量的内容,如果多个线程只是读取一个变量,不修改,此时任然是线程安全的。如下所示 ? 1.2懒汉模式举个例子解释懒汉模式:中午使用了三个菜碟,吃完后,先放着,晚上需要一个就洗一个,需要两个就洗两个,剩下的不管。 相对于饿汉模式来说,懒汉模式更加高效。 如下代码是完全体的线程安全单例模式,具有1.正确的位置加锁,2.双重 if 淡定。3.volatile
?懒汉模式中即包含了读,又包含了修改。但是这里的读和修改,是分为两个步骤的(不是原子性),存在线程安全问题,,因此需要加锁synchronized。加锁可能导致代码出现阻塞,外层条件可能执行几分钟几分钟之后里层才开始执行。在这个执行的时间差中间,instance也可能被其他线程给修改的。 2.阻塞队列
阻塞队列是一种特殊的队列
.
也遵守
"
先进先出
"
的原则
.
阻塞队列能是一种线程安全的数据结构
,
并且具有以下特性
:
?阻塞队列的一个典型应用场景就是 "生产者消费者模型". 这是一种非常典型的开发模型。
生产者消费者模型 :
生产者消费者模式就是通过一个容器来解决生产者和消费者的强耦合问题。
生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等 待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取。
(1)阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。
(2)阻塞队列也能使生产者和消费者之间解耦。
?应用: 生产者消费者模型,是实际开发中非常有用的一种多线程开发手段,尤其是在服务器开发场景中。 假设,有两个服务器A、B。A作为入口服务器直接接收用户的网络请求,B作为应用服务器,来给A提供数据。 1)通常情况下 未使用生产者消费者模型如下图所示 ?如果不使用生产者消费者模型,此时的A和B的耦合性是比较强的,在开发A代码的时候就得到充分了解B的一些接口。开发B代码的时候也得充分了解到A是怎样调用的。一旦想把B换成C,A的代码就需要较大的改动。如果B没了,也可能直接导致A也没了。 因此,使用生产者消费者模型,就可以降低这里的耦合,如下图所示 优点一:能够让多个服务器程序之间更充分的解耦合 对于请求:A是生产者,B是消费者 对于响应:A是消费者,B是生产者 阻塞队列是作为交易场所。 ?A只需要关注如何与队列交互,不需要认识B。 B也只需要关注如何与队列交互,也不需要认识A。 A与B直接互不影响。 2)暴涨情况下 未使用生产者消费者模型如下图所示 当 ?当请求量突然暴涨不可控的时候,A作为入口服务器,计算量很轻,请求暴涨,问题不大。但是B作为应用服务器,计算量可能很大,需要的系统资源也更多,如果请求更多了,需要的资源进一步增加,如果主机的硬件不够,可能程序就撑不住了。 ?使用生产者消费者模型如下图所示 优点二:能够对于请求进行“削峰填谷” 当A请求暴涨时=>阻塞队列的请求暴涨。由于阻塞队列没什么计算量,就单纯的存个数据,就能抗住跟大的压力。B任然按照原来的速度来消费数据,不会因为A的暴涨而引起暴涨。 “削峰” 指的是峰值很多时候不是持续的,就一阵子,过去了就又恢复了。 “填谷” B任然按照原来的频率来处理之前的积压数据。 2.1阻塞队列的实现(生产者消费者模型)
通过
"
循环队列
"
的方式来实现
.
使用
synchronized
进行加锁控制
.
put
插入元素的时候
,
判定如果队列满了
,
就进行
wait. (
注意
,
要在循环中进行
wait.
被唤醒时不一
定队列就不满了
,
因为同时可能是唤醒了多个线程
).
take
取出元素的时候
,
判定如果队列为空
,
就进行
wait. (
也是循环
wait)
|
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/23 20:00:49- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |