- 博客(144)
- 收藏
- 关注
原创 结构型设计模式--装饰模式
装饰模式可以在不改变一个对象本身功能的基础上给对象增加额外的新行为。在现实生活中,这种情况也到处存在。例如一张照片,可以不改变照片本身,给它增加一个相框,使得它具有防潮的功能,而且用户可以根据需要给它增加不同类型的相框,甚至可以在一个小相框的外面再套一个大相框。**装饰模式是一种用于替代继承的技术,它通过一种无须定义子类的方式来给对象动态增加职责,使用对象之间的关联关系取代类之间的继承关系。**在装饰模式中引入了装饰类,在装饰类中既可以调用待装饰的原有类的方法,还可以增加新的方法,以扩充原有类的功能。
2024-09-05 21:54:18
1288
原创 结构型设计模式—外观模式
根据单一职责原则,在软件中将一个系统划分为若干个子系统(subSystem)有利于降低整个系统的复杂性。一个常见的设计模式是使客户端与子系统之间的通信和相互依赖的关系达到最小,而达到该目前的途径之一就是引入一个外观(Facade)角色,它为子系统的访问提供了一个简单而单一的入口。外观模式也是迪米特法则的体现,通过引入一个新的外观角色可以降低原有系统的复杂度,同时降低客户类与子系统类的耦合度。如果没有外观角色,每个客户端可能需要和多个子系统之间进行复杂的交互,系统的耦合度将很大,如图所示。
2024-09-05 21:49:31
1426
原创 结构型设计模式—组合模式
对于树形结构,当容器对象(例如文件夹)的某一个方法被调用时,将遍历整个树形结构,寻找也包含这个方法的成员对象(可以是容器对象,也可以是叶子对象)并调用执行,牵一而动百,其中使用了递归调用的机制来对整个结构进行处理。由于容器对象和叶子对象在功能上的区别,在使用这些对象的代码中必须有区别地对待容器对象和叶子对象,而实际上大多数情况下希望一致地处理它们,因为对于这些对象的区别对待将会使得程序非常复杂。组合模式为解决此类问题而诞生,它可以让叶子对象和容器对象的使用具有一致性。
2024-09-03 22:54:01
1082
原创 结构型设计模式—桥接模式
桥接模式是一种很实用的结构型设计模式。如果软件系统中某个类存在两个独立变化的维度,通过该模式可以将这两个维度分离出来,使两者可以独立扩展,让系统更加符合单一职责原则。与多层继承方案不同,它将两个独立变化的维度设计为两个独立的继承等级结构,并且在抽象层建立一个抽象关联,该关联关系类似一条连接两个独立继承结构的桥,故名桥接模式。桥接模式用一种巧妙的方式处理多层继承存在的问题。
2024-09-03 22:52:48
1329
原创 创建型模式--抽象工厂模式
抽象工厂模式为创建一组对象提供了一种解决方案。与工厂方法模式相比,抽象工厂模式中的具体工厂不只是创建一种产品,它负责创建一族产品。抽象工厂模式定义如下:抽象工厂模式(Abstract Factory Pattern):提供一个创建一系列相关或相互依赖对象的接口,而无须指定它们具体的类。抽象工厂模式又称为Kit模式,它是一种对象创建型模式。在抽象工厂模式中,每个具体工厂都提供了多个工厂方法用于产生多种不同类型的产品,这些产品构成了一个产品族。抽象工厂模式结构如图所示。
2024-06-17 22:55:33
1220
原创 创建型模式--工厂方法模式
在工厂方法模式中,不再提供一个统一的工厂类来创建所有的产品对象,而是针对不同的产品提供不同的工厂,系统提供一个与产品等级结构对应的工厂等级结构。工厂方法模式定义如下:工厂方法模式(Factory Method Pattern):定义一个用于创建对象的接口,让子类决定将哪一个类实例化。工厂方法模式让一个类的实例化延迟到其子类。
2024-06-17 22:53:26
995
原创 创建型模式--简单工厂模式
简单工厂模式定义如下:简单工厂模式(Simple Factory Pattern):定义一个工厂类,它可以根据参数的不同返回不同类的实例,被创建的实例通常都具有共同的父类。因为在简单工厂模式中用于创建实例的方法是静态(static)方法,因此简单工厂模式又被称为静态工厂方法(Static Factory Method)模式,它属于类创建型模式。简单工厂模式的要点在于:当你需要什么,只需要传入一个正确的参数,就可以获取你所需要的对象,而无须知道其创建细节。
2024-06-17 22:52:28
1114
原创 UML精简概述
UML是英文 Unified Modeling Language 的缩写,简称UML(统一建模语言),它是一种由一整套图组成的标准化建模语言,用于帮助系统开发人员阐明、设计和构建软件系统。UML 的这一整套图被分为两组,一组叫结构性图,包含类图、组件图、部署图、对象图、包图、组合结构图、轮廓图;一组叫行为性图,包含用例图、活动图(也叫流程图)、状态机图、序列图、通信图、交互图、时序图。其中类图是应用最广泛的一种图,经常被用于软件架构设计中。
2024-06-11 22:25:05
1286
原创 公平锁和非公平锁,为什么要“非公平”?
首先,我们来看下什么是公平锁和非公平锁,公平锁指的是按照线程请求的顺序,来分配锁;而非公平锁指的是不完全按照请求的顺序,在一定情况下,可以允许插队。但需要注意这里的非公平并不是指完全的随机,不是说线程可以任意插队,而是仅仅“在合适的时机”插队。那么什么时候是合适的时机呢?假设当前线程在请求获取锁的时候,恰巧前一个持有锁的线程释放了这把锁,那么当前申请锁的线程就可以不顾已经等待的线程而选择立刻插队。但是如果当前线程请求的时候,前一个线程并没有在那一时刻释放锁,那么当前线程还是一样会进入等待队列。
2024-03-25 22:56:55
840
原创 为什么使用多线程可能会带来性能问题
多线程会带来的线程安全问题,但对于多线程而言,它不仅可能会带来线程安全问题,还有可能会带来性能问题,也许你会奇怪,我们使用多线程的最大目的不就是为了提高性能吗?让多个线程同时工作,加快程序运行速度,为什么反而会带来性能问题呢?这是因为单线程程序是独立工作的,不需要与其他线程进行交互,但多线程之间则需要调度以及合作,调度与合作就会带来性能开销从而产生性能问题。首先,我们来了解究竟什么是性能问题?其实性能问题有许多的表现形式,比如服务器的响应慢、吞吐量低、内存占用过多就属于性能问题。
2024-03-21 21:15:52
749
原创 一共有哪 3 类线程安全问题
然后假设等线程 2 对 i 进行 +1 操作后,又切换到线程 1,让线程 1 完成未完成的操作,即将 i+1 的结果 2 保存下来,然后又切换到线程 2 完成 i=2 的保存操作,虽然两个线程都执行了对 i 进行 +1 的操作,但结果却最终保存了 i=2 的结果,而不是我们期望的 i=3,这样就发生了线程安全问题,导致了数据结果错误,这也是最典型的线程安全问题,i+1的操作不是原子性的操作。第二种活跃性问题是活锁,活锁与死锁非常相似,也是程序一直等不到结果,但对比于死锁,活锁是活的,什么意思呢?
2024-03-20 21:49:07
910
原创 生产者消费者模式
而此时,如果生产者生产了一个数据,便会唤醒两个消费者线程,而两个线程中只有一个线程可以拿到锁,并执行 queue.remove 操作,另外一个线程因为没有拿到锁而卡在被唤醒的地方,而第一个线程执行完操作后会在 finally 中通过 unlock 解锁,而此时第二个线程便可以拿到被第一个线程释放的锁,继续执行操作,也会去调用 queue.remove 操作,然而这个时候队列已经为空了,所以会抛出。生产者负责生产数据,消费者负责处理数据,通过合理的协作,可以实现高效的数据处理。如何才能让大家更好地配合呢?
2024-03-20 20:57:29
1183
原创 wait/notify/notifyAll 方法的使用注意事项
我们来看第二个问题,为什么 wait/notify/notifyAll 方法被定义在 Object 类中?而 sleep 方法定义在 Thread 类中?因为 Java 中每个对象都有一把称之为 monitor 监视器的锁,由于每个对象都可以上锁,这就要求在对象头中有一个用来保存锁信息的位置。这个锁是对象级别的,而非线程级别的,wait/notify/notifyAll 也都是锁级别的操作,它们的锁属于对象,所以把它们定义在 Object 类中是最合适,因为 Object 类是所有对象的父类。
2024-03-17 12:18:44
974
原创 线程是如何在 6 种状态之间转换的
因为唤醒 Waiting 线程的线程如果调用 notify() 或 notifyAll(),要求必须首先持有该 monitor 锁,所以处于 Waiting 状态的线程被唤醒时拿不到该锁,就会进入 Blocked 状态,直到执行了 notify()/notifyAll() 的唤醒它的线程执行完毕并释放 monitor 锁,才可能轮到它去抢夺这把锁,如果它能抢到,就会从 Blocked 状态回到 Runnable 状态。下面我们逐个介绍线程的 6 种状态,如图所示,首先来看下左上角的 New 状态。
2024-03-17 11:30:30
1070
原创 使用了并发工具类库,线程安全就高枕无忧了吗?
今天想和大家聊聊使用并发工具类库相关的话题。在代码审核讨论的时候,我们有时会听到有关线程安全和并发工具的一些片面的观点和结论,比如“把 HashMap 改为 ConcurrentHashMap,就可以解决并发问题了呀”“要不我们试试无锁的 CopyOnWriteArrayList 吧,性能更好”。事实上,这些说法都不太准确。的确,为了方便开发者进行多线程编程,现代编程语言会提供各种并发工具类。
2024-03-10 21:33:01
794
原创 Java实现异步回调
设想一个情景,A是处理业务的一个步骤,A需要解决一个问题,这时候A可以问B,让B来告诉A答案,这期间,A可以继续做自己的事情,而不用因为B做的事而阻塞。于是,我们想到给B设置一个线程,让B去处理耗时的操作,然后处理完之后把结果告诉A。所以这个问题的要点就在于B处理完之后如何把结果告诉A。
2024-02-03 20:19:42
2224
1
原创 如何在 Mac 上重置网络设置
如果您经常使用 VPN,则您的系统上的网络设置可能会被弄乱。 Internet 设置可能非常敏感,因为即使是最轻微的更改或调整也可能导致与 Internet 的连接中断。
2024-02-03 20:12:32
16893
原创 分布式锁有哪些应用场景和实现
这一课时分享了分布式锁的应用场景和几种实现,包括分布式锁的概念,使用数据库方式、缓存和 ZooKeeper 实现分布式锁等。
2023-03-15 23:23:41
867
原创 “消息驱动、事件驱动、流 ”的消息模型
事件驱动 EDA 作为 Gartner 预测的十大技术趋势之一, EventBridge 作为下一代消息中间件,也是目前的重点方向之一。
2023-02-17 17:14:51
838
原创 AMQP 0-9-1 模型解释
官方文档链接:https://www.rabbitmq.com/tutorials/amqp-concepts.html。
2023-01-29 21:35:32
671
原创 Java中「与运算,或运算,异或运算,取反运算。」
即:参加运算的两个对象,如果两个相应位为“异”(值不同),则该位结果为1,否则为0。即 :参加运算的两个对象只要有一个为1,其值为1。即:两位同时为“1”,结果才为“1”,否则为0。
2023-01-29 10:37:21
3269
原创 面试中如何回答缓存穿透、击穿、雪崩等问题
上一篇,我们一起学习了Redis缓存数据库的原理(比如线程模型、数据持久化、以及数据复制)。这一篇,我们从应用案例入手,来了解经常遇到的缓存设计中存在的问题,比如缓存雪崩、缓存并发、缓存穿透等。
2022-09-22 22:52:17
836
原创 进程间通信都有哪些方法
在上一讲中,我们提到过进程间通信三种方式,凡是面试官问“什么情况下”的时候,面试官实际想听的是你经过理解,整理得到的认知。回答应该是概括的、简要的。而不是真的去列举每一种 case。另外,面试官考察进程间通信,有一个非常重要的意义——进程间通信是架构复杂系统的基石。复杂系统往往是分成各种子系统、子模块、微服务等等,按照 `Unix` 的设计哲学,系统的每个部分应该是稳定、独立、简单有效,而且强大的。系统本身各个模块就像人的器官,可以协同工作。而这个协同的枢纽,就是我们今天的主题——进程间通信
2022-09-07 18:16:40
482
SpringBoot一个启动程序启动多个SpringBoot应用程序
2024-06-16
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人