当前位置:网站首页>【手撕代码】单例模式及生产者/消费者模式
【手撕代码】单例模式及生产者/消费者模式
2022-07-06 09:20:00 【李孛欢】
单例模式
单例模式(Singleton Pattern):保证一个类仅有一个对象,并提供一个访问它的全局访问点。
单例模式的优点:
由于单例模式只生成一个实例,减少了系统性能开销,当一个对象的产生需要比较多的资源时,如读取配置、产生其他依赖对象时,则可以通过在应用启动 时直接产生一个单例对象,然后永久驻留内存的方式来解决
单例模式可以在系统设置全局的访问点,优化环共享资源访问,例如可以设计 一个单例类,负责所有数据表的映射处理
代码实现:
饿汉式 :先创建后使用,线程安全,占用内存。
public class SingleClassA {
//1.私有化构造方法,使得在类的外部不能调用此方法,限制产生多个对象
private SingleClassA(){ }
//2.在类的内部创建一个类的实例
//类初始化时,立即加载这个对象(没有延时加载的优势)。加载类时,天然的是线程安全的!
private static final SingleClassA instance = new SingleClassA();
//3.对外部提供调用方法:将创建的对象返回,只能通过类来调用
//方法没有同步,调用效率高!
public static SingleClassA getInstance(){
return instance;
}
public static void main(String[] args) {
SingleClassA a = getInstance();
SingleClassA b = getInstance();
System.out.println(a == b);
}
}
输出结果:
懒汉式:用的时候才创建,线程不安全(创建或获取单例对象时),加锁会影响效率。
public class SingleClassB {
//1.私有化构造方法,使得在类的外部不能调用此方法,限制产生多个对象
private SingleClassB(){ }
//2.在类的内部创建一个类的实例
private static SingleClassB instance ;
//3.对外部提供调用方法:将创建的对象返回,只能通过类来调用
public static synchronized SingleClassB getInstance(){
if(instance == null) {
instance = new SingleClassB();
}
return instance;
}
//测试
public static void main(String[] args) {
SingleClassB a = SingleClassB.getInstance();
SingleClassB b = SingleClassB.getInstance();
System.out.println(a==b);
}
}
输出结果:
懒汉模式和饿汉模式的区别:
- 懒汉式默认不会实例化,要等到外部调用方法时才会,饿汉式类加载阶段就实例化了对象
- 线程安全上,饿汉式肯定是线程安全的,因为在线程没出现之前就实例化了对象,懒汉式则是线程不安全的,因为在多线程下,如果一个线程判断完实例为null就休眠或着中断,那么另一个线程也进入方法,判断实例也为null,那么该线程就会创建实例对象,而原来的那个休眠线程恢复以后,直接就执行实例化new对象这一步,那么就会出现多个实例。
- 分析上面的线程安全,接下来就是性能了,可能你已经想到了,饿汉式不需要加锁,执行效率高,懒汉式需要加锁,执行效率低
- 占用内存上,饿汉式不管你用不用到它的实例对象,他一开始就已经实例化在那里了,占据了内存空间,而懒汉式等到用的时候才实例化,不会浪费内存
生产者/消费者模式
生产者消费者模式是通过一个容器来解决生产者和消费者的强耦合问题。生产者和消费者彼此之间不直接通讯,而通过阻塞队列来进行通讯,所以生产者生产完数据之后不用等待消费者处理,直接扔给阻塞队列,消费者不找生产者要数据,而是直接从阻塞队列里取,阻塞队列就相当于一个缓冲区,平衡了生产者和消费者的处理能力。如下图所示:
代码实现:
@Slf4j(topic = "ProductAndConsumer")
public class ProductAndConsumer {
public static void main(String[] args) {
MessageQueue messageQueue = new MessageQueue(2);
// 3 个生产者线程
for (int i = 0; i < 3; i++) {
int id = i;
new Thread(() -> {
messageQueue.put(new Message(id, "值" + id));
}, "生产者" + i).start();
}
// 1 个消费者线程, 处理结果
new Thread(() -> {
while (true) {
try {
sleep(1000);
Message message = messageQueue.take();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "消费者").start();
}
}
final class Message {
private int id;
private Object message;
public Message(int id, Object message) {
this.id = id;
this.message = message;
}
public int getId() {
return id;
}
public Object getMessage() {
return message;
}
@Override
public String toString() {
return "Message{" +
"id=" + id +
", message=" + message +
'}';
}
}
@Slf4j(topic = "MessageQueue")
class MessageQueue {
private LinkedList<Message> queue;
private int capacity;
public MessageQueue(int capacity) {
this.capacity = capacity;
queue = new LinkedList<>();
}
public Message take() {
synchronized (queue) {
while (queue.isEmpty()) {
log.debug("队列为空,消费者线程等待");
try {
queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
Message message = queue.removeFirst();
log.debug("已消费消息{}",message);
queue.notifyAll();
return message;
}
}
public void put(Message message) {
synchronized (queue) {
while (queue.size() == capacity) {
try {
log.debug("库存已达上限, 生产者线程等待");
queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
queue.addLast(message);
log.debug("已生产消息{}",message);
queue.notifyAll();
}
}
}
输出结果如下:
边栏推荐
- 更改VS主题及设置背景图片
- The overseas sales of Xiaomi mobile phones are nearly 140million, which may explain why Xiaomi ov doesn't need Hongmeng
- arduino+DS18B20温度传感器(蜂鸣器报警)+LCD1602显示(IIC驱动)
- fianl、finally、finalize三者的区别
- [the Nine Yang Manual] 2017 Fudan University Applied Statistics real problem + analysis
- 关于双亲委派机制和类加载的过程
- MPLS experiment
- MySQL limit x, -1 doesn't work, -1 does not work, and an error is reported
- 1.C语言矩阵加减法
- 受检异常和非受检异常的区别和理解
猜你喜欢
5. Download and use of MSDN
Summary of multiple choice questions in the 2022 database of tyut Taiyuan University of Technology
3.C语言用代数余子式计算行列式
IPv6 experiment
C language Getting Started Guide
最新坦克大战2022-全程开发笔记-1
System design learning (I) design pastebin com (or Bit.ly)
1.初识C语言(1)
The latest tank battle 2022 - Notes on the whole development -2
凡人修仙学指针-1
随机推荐
20220211-CTF-MISC-006-pure_ Color (use of stegsolve tool) -007 Aesop_ Secret (AES decryption)
【九阳神功】2020复旦大学应用统计真题+解析
最新坦克大战2022-全程开发笔记-1
12 excel charts and arrays
A brief introduction to the database of tyut Taiyuan University of technology in previous years
重载和重写的区别
【毕业季·进击的技术er】再见了,我的学生时代
【九阳神功】2017复旦大学应用统计真题+解析
3. C language uses algebraic cofactor to calculate determinant
vector
CorelDRAW plug-in -- GMS plug-in development -- Introduction to VBA -- GMS plug-in installation -- Security -- macro Manager -- CDR plug-in (I)
Atomic and nonatomic
六种集合的遍历方式总结(List Set Map Queue Deque Stack)
(超详细onenet TCP协议接入)arduino+esp8266-01s接入物联网平台,上传实时采集数据/TCP透传(以及lua脚本如何获取和编写)
Rich Shenzhen people and renting Shenzhen people
View UI Plus 发布 1.2.0 版本,新增 Image、Skeleton、Typography组件
【九阳神功】2022复旦大学应用统计真题+解析
ABA问题遇到过吗,详细说以下,如何避免ABA问题
View UI plus releases version 1.1.0, supports SSR, supports nuxt, and adds TS declaration files
The latest tank battle 2022 - full development notes-3