- 博客(157)
- 收藏
- 关注
原创 Freemarker指令语法详细总结
1、注释,即<#-- -->,介于其之间的内容会被freemarker忽略2、插值(Interpolation):即 ${..}部分,freemarker会用真实的值代替${..}3、FTL指令:和HTML标记类似,名字前加#予以区分,Freemarker会解析标签中的表达式或逻辑。4、文本,仅文本信息,这些不是freemarker的注释、插值、FTL指令的内容会被freemarker忽略解析,直接输出内容。
2024-08-03 15:39:29
940
原创 消息队列之MQ的可靠性
为了提升性能,默认情况下MQ的数据都是在内存存储的临时数据,重启后就会消失。为了保证数据的可靠性,必须配置数据持久化,包括:交换机持久化队列持久化消息持久化在开启持久化机制以后,如果同时还开启了生产者确认,那么MQ会在消息持久化以后才发送ACK回执,进一步确保消息的可靠性。不过出于性能考虑,为了减少IO次数,发送到MQ的消息并不是逐条持久化到数据库的,而是每隔一段时间批量持久化。一般间隔在100毫秒左右,这就会导致ACK有一定的延迟,因此建议生产者确认全部采用异步方式。
2024-07-26 00:15:00
337
原创 消息队列之消费者的可靠性
为了确认消费者是否成功处理消息,RabbitMQ提供了消费者确认机制(即:当消费者处理消息结束后,应该向RabbitMQ发送一个回执,告知RabbitMQ自己消息处理状态。回执有三种可选值:ack:成功处理消息,RabbitMQ从队列中删除该消息nack:消息处理失败,RabbitMQ需要再次投递消息reject:消息处理失败并拒绝该消息,RabbitMQ从队列中删除该消息一般reject方式用的较少,除非是消息格式有问题,那就是开发问题了。因此大多数情况下我们需要将消息处理的代码通过。
2024-07-26 00:15:00
754
原创 消息队列之发送者的可靠性
每个只能配置一个,因此我们可以在配置类中统一设置。@Slf4j@Overridelog.error("触发return callback,");});由于每个消息发送时的处理逻辑不一定相同,因此ConfirmCallback需要在每次发消息时定义。具体来说,是在调用RabbitTemplate中的convertAndSend方法时,多传递一个参数:id:消息的唯一标示,MQ对不同的消息的回执以此做判断,避免混淆:回执结果的Future对象将来MQ的回执就会通过这个Future。
2024-07-25 17:06:30
1074
原创 SpringAMQP详细总结(二)
交换机的作用是什么?接收publisher发送的消息将消息按照规则路由到与之绑定的队列不能缓存消息,路由失败,消息丢失FanoutExchange的会将消息路由到每个绑定的队列声明队列、交换机、绑定关系的Bean是什么?QueueBinding描述下Direct交换机与Fanout交换机的差异?Fanout交换机将消息路由给每一个与之绑定的队列Direct交换机根据RoutingKey判断路由给哪个队列如果多个队列具有相同的RoutingKey,则与Fanout功能类似。
2024-07-25 11:34:25
778
原创 SpringAMQP详细总结(一)
Work模型的使用:多个消费者绑定到一个队列,同一条消息只会被一个消费者处理通过设置prefetch来控制消费者预取的消息数量。
2024-07-24 22:58:09
920
原创 初始RabbitMQ消息模型
基本消息队列的消息发送流程:建立connection创建channel利用channel声明队列利用channel向队列发送消息基本消息队列的消息接收流程:建立connection创建channel利用channel声明队列定义consumer的消费行为handleDelivery()利用channel将消费者与队列绑定。
2024-07-24 22:33:01
411
原创 Spring IOC详细总结
IOC-Inversion of Control,控制反转,就是把创建和管理 bean 的过程转移给了第三方。而这个第三方,就是 Spring IoC Container,对于 IoC 来说,最重要的就是容器负责创建、配置和管理 bean,也就是它管理着 bean 的生命,控制着 bean 的依赖注入eanBean 其实就是包装了的 Object,无论是控制反转还是依赖注入,它们的主语都是 object,而 bean 就是由第三方包装好了的 object。
2024-07-23 12:46:18
1078
原创 OSI网络七层模型详细总结
随着网络通信需求的进一步扩大,通信过程中需要发送大量的数据,如海量文件传输,可能需要很长时间,网络在通信的过程中会中断很多次,此时为了保证传输大量文件时的准确性,需要对发送出去的数据进行切分,切割为一个一个的段落(规定发送方和接收方必须使用一个固定长度的消息头,消息头必须使用某种固定的组成,消息头中必须记录消息体的长度等信息,方便接收方正确解析发送方发送的数据。物理层主要定义了物理设备的标准,如网线的类型,光纤的接口类型,各种传输介质的传输速率。该层负责物理层面上互连的节点之间的通信传输。
2024-07-21 08:53:45
603
原创 分布式搜索之Elasticsearch入门
Elasticsearch 是一个分布式、RESTful 风格的搜索和数据分析引擎,能够解决不断涌现出的各种用例。作为 Elastic Stack 的核心,它集中存储您的数据,帮助您发现意料之中以及意料之外的情况。Elastic Stack 又是什么呢?整个架构图如下图(来源于网络,侵删)所示Elasticsearch 有很多强大的功能,比如说全文搜索、购物推荐、附近定位推荐等等。
2024-07-20 13:53:36
849
原创 UDP详细总结
UDP是无连接的传输层协议;UDP使用尽最大努力交付,不保证可靠交付;UDP是面向报文的,对应用层交下来的报文,不合并,不拆分,保留原报文的边界;UDP没有拥塞控制,因此即使网络出现拥塞也不会降低发送速率;UDP支持一对一 一对多 多对多的交互通信;UDP的首部开销小,只有8字节TCP是可靠传输,UDP是不可靠传输;TCP面向连接,UDP无连接;TCP传输数据有序,UDP不保证数据的有序性;TCP不保存数据边界,UDP保留数据边界;TCP传输速度相对UDP较慢;
2024-07-20 11:34:10
767
原创 TCP总结
TCP是一个传输层协议,提供可靠传输,支持全双工,是一个连接导向的协议。在任何一个时刻,如果数据只能单向发送,就是单工。如果在某个时刻数据可以向一个方向传输,也可以向另一个方向反向传输,而且交替进行,叫作半双工;半双工需要至少 1 条线路。如果任何时刻数据都可以双向收发,这就是全双工,全双工需要大于 1 条线路。TCP 是一个双工协议,数据任何时候都可以双向传输。这就意味着客户端和服务端可以平等地发送、接收信息。;
2024-07-20 11:25:34
1006
原创 深入理解Java并发线程阻塞唤醒类LockSupport
LockSupprot 用来阻塞和唤醒线程,底层实现依赖于Unsafe类该类包含一组用于阻塞和唤醒线程的静态方法,这些方法主要是围绕 park 和 unpark 展开上面的代码中,当 counterThread 数到 500 时,它会唤醒 mainThread。而 mainThread 在调用 park 方法时会被阻塞,直到被 unpark。
2024-07-20 03:15:00
975
原创 Java Condition 的 await 和 signal 等待通知机制
Condition 接口一共提供了以下 7 个方法: 我们再来回顾一下 Object 类的主要方法: 当调用方法后会使当前获取锁的线程进入到等待队列,如果该线程能够从 方法返回的话,一定是该线程获取了与 Condition 相关联的锁。Condition 只是一个接口,它的实现类为 ConditionObject,是 AQS 的子类。 ConditionObject 的 await 方法源码如下: 当前线程调用方法后,会释放 lock 然后加入到等待队列,直到被 方法唤
2024-07-20 02:30:00
862
原创 什么是AQS(抽象队列同步器)?
是的简称,即抽象队列同步器AQS 是一个用来构建锁和同步器的框架,使用 AQS 能简单且高效地构造出应用广泛的同步器,比如我们后面会细讲的ReentrantLock,Semaphore,ReentrantReadWriteLock,SynchronousQueue,FutureTask 等等,都是基于 AQS 的。
2024-07-19 21:36:26
826
原创 滑动窗口算法
那么当我们选择第 k+1字符作为起始位置时,首先从 k+1到 rk的字符显然是不重复的,并且由于少了原本的第 k个字符,我们可以尝试继续增大 rk,直到右侧出现了重复字符为止。在这种情况下,我们可以通过不断地增加窗口的右边界,并根据当前窗口内的和来移动左边界,以找到最短的满足条件的子数组。这种算法的关键在于如何有效地移动窗口,并在每个步骤中更新窗口内的状态,以在满足特定条件时找到所需的结果。这种算法通常具有较低的时间复杂度,因为在每个步骤中,只需要对窗口中的元素进行常数级别的操作。
2024-07-18 22:55:43
408
原创 Spring事务失效场景详细总结(下)
在使用@Transactional注解声明事务时,有时我们想自定义回滚的异常,spring也是支持的。可以通过设置参数,来完成这个功能。@Service如果在执行上面这段代码,保存和更新数据时,程序报错了,抛了SqlException、DuplicateKeyException等异常。而BusinessException是我们自定义的异常,报错的异常不属于BusinessException,所以事务也不会回滚。
2024-07-18 00:00:00
770
原创 Spring事务失效场景详细总结(上)
java的访问权限主要有四种:private、default、protected、public,它们的权限从左到右,依次变大。spring要求被代理方法必须是public的在类的方法中有个判断,如果目标方法不是public,则返回null,即不支持事务。如果我们自定义的事务方法(即目标方法),它的访问权限不是public,而是private、default或protected的话,spring则不会提供事务功能。
2024-07-17 14:15:51
1157
原创 Spring Boot 开启事务支持详细总结
要在 public 方法上使用,在AbstractFallbackTransactionAttributeSource类的computeTransactionAttribute方法中有个判断,如果目标方法不是public,则TransactionAttribute返回null,即不支持事务。避免同一个类中调用 @Transactional 注解的方法,这样会导致事务失效。
2024-07-17 09:12:00
1389
原创 Java NIO的Buffer缓冲区和Channel通道详细总结
NIO 主要有在 NIO 中,并不是以流的方式来处理数据的,而是以 buffer 缓冲区和 Channel 通道来处理数据的。可以简单理解为把Channel通道比作 铁路,buffer缓冲区比作成火车(运载着货物),而NIO就是通过来实现数据的处理。Buffer 是缓冲区的抽象类,ByteBuffer 是(在通道中读写字节数据):拿到一个缓冲区我们往往会做什么?很简单,就是。所以,缓冲区的核心方法就是 put 和 get:Buffer 类维护了 4 个核心变量来提供。get()put()现在,怎么拿呀。
2024-07-16 15:02:17
1150
原创 Java 中的NIO、BIO和AIO详细总结
使用非阻塞 I/O 模型,线程在等待 I/O 时可执行其他任务,通过 Selector 监控多个 Channel 上的事件,提高性能和可伸缩性,适用于高并发场景。:这种模式下,我们的工作模式是先来到厨房,开始烧水,我们不一直坐在水壶前面等,也不隔一段时间去看一下,而是在客厅看电视,水壶上面有个开关,水烧开之后他会通知我。最后,关闭文件通道。:采用异步 I/O 模型,线程发起 I/O 请求后立即返回,当 I/O 操作完成时通过回调函数通知线程,进一步提高了并发处理能力,适用于高吞吐量场景。
2024-07-16 09:10:14
913
原创 Java NIO 比传统 IO 强在哪里?
这里先给大家展示一副传统 IO 和 NIO 的对比图,感受一下。传统IO基于字节流或字符流(如 FileInputStream、BufferedReader 等)进行文件读写,以及使用Socket和ServerSocketChannel进行网络传输。NIO 使通道(Channel)和缓冲区(Buffer)进行文件操作,以及使用 SocketChannel 和 ServerSocketChannel 进行网络传输。传统 IO 采用阻塞式模型,对于每个连接,都需要创建一个独立的线程来处理读写操作。
2024-07-16 03:30:00
1192
原创 RandomAccessFile详细总结
RandomAccessFile 是 Java 中一个非常特殊的类,它既可以用来读取文件,也可以用来写入文件。与其他 IO 类(如 FileInputStream 和 FileOutputStream)不同,RandomAccessFile 允许您跳转到文件的任何位置,从那里开始读取或写入。这使得它特别适用于需要在文件中随机访问数据的场景,如数据库系统。为了避免中文乱码问题,我们使用 RandomAccessFile 的 writeUTF 和 readUTF 方法,它们将使用 UTF-8 编码处理字符串。
2024-07-15 22:55:18
853
原创 Java中stream流
要想操作流,首先需要有一个数据源,可以是数组或者集合。每次操作都会返回一个新的流对象,方便进行链式操作,但原有的流对象会保持不变。distinct()方法是一个中间操作(去重),它会返回一个新的流(没有共同元素)。count()方法是一个终端操作,返回流中的元素个数。中间操作不会立即执行,只有等到终端操作的时候,流才开始真正地遍历,用于映射、过滤等。通俗点说,就是一次遍历执行多个操作,性能就大大提高了。
2024-07-15 00:15:00
979
原创 Collections:专为集合框架而生的工具类
Collections 是 JDK 提供的一个工具类,位于 java.util 包下,提供了一系列的静态方法。
2024-07-14 00:15:00
354
原创 Hutool工具类
Maven 项目只需要在 pom.xml 文件中添加以下依赖即可。Hutool 的设计思想是尽量减少重复的定义,让项目中的 util 包尽量少。一个好的轮子可以在很大程度上避免“复制粘贴”,从而节省我们开发人员对项目中公用类库和公用工具方法的封装时间。
2024-07-14 00:15:00
829
原创 Arrays:专为数组而生的工具类
revised 和 expanded 是复制后的新数组,长度分别是 3 和 5,指定的数组长度是 4。revised 截取了最后一位,因为长度是 3 嘛;expanded 用 null 填充了一位,因为长度是 5。
2024-07-13 00:15:00
935
原创 StringUtils:专为Java字符串而生的工具类
分隔字符串是常见需求,如果直接使用 String 类的 split 方法,就可能会出现空指针异常。其实空字符串,不只是 null 一种,还有""," ","null"等等,多种情况。将某个集合的内容,拼接成一个字符串,然后输出,这时可以使用。给定一个字符串,判断它是否为纯数字,可以使用。
2024-07-13 00:15:00
375
原创 Java Comparable和Comparator的区别
Comparable 和 Comparator 是 Java 的两个接口,从名字上我们就能够读出来它们俩的相似性:以某种方式来比较两个对象。
2024-07-12 00:15:00
633
原创 Scanner工具类
在上面的示例中,我们首先创建了一个 File 对象,表示要扫描的文件。然后,我们使用 Scanner 类的构造方法来创建 Scanner 对象,将文件作为参数传递给构造方法。在上面的示例中,我们首先创建了一个字符串 input,表示要查找的文本。然后,我们使用 Scanner 类的构造方法创建 Scanner 对象,并将 input 作为输入流传递给该对象。总之,Scanner 类是一个功能强大的输入处理工具类,不仅可以扫描控制台的输入流,还可以扫描文件,并且提供了多种方法来读取不同类型的数据,比如。
2024-07-12 00:15:00
427
原创 Java中HashMap详解:hash原理、扩容机制、线程不安全及源码分析
HashMap 是 Java 中常用的数据结构之一,用于存储键值对。在 HashMap 中,每个键都映射到一个唯一的值,可以通过键来快速访问对应的值,算法时间复杂度可以达到 O(1)。HashMap 的实现原理是基于哈希表的,它的底层是一个数组,数组的每个位置可能是一个链表或红黑树,也可能只是一个键值对。当添加一个键值对时,HashMap 会根据键的哈希值计算出该键对应的数组下标(索引),然后将键值对插入到对应的位置。当通过键查找值时,HashMap 也会根据键的哈希值计算出数组下标,并查找对应的值。
2024-07-11 16:09:19
1770
原创 单队列实现栈
入栈操作时,首先获得入栈前的元素个数 n,然后将元素入队到队列,再将队列中的前 n 个元素(即除了新入栈的元素之外的全部元素)依次出队并入队到队列,此时队列的前端的元素即为新入栈的元素,且队列的前端和后端分别对应栈顶和栈底。出栈操作只需要移除队列的前端元素并返回即可,获得栈顶元素操作只需要获得队列的前端元素并返回即可(不移除元素)。使用一个队列时,为了满足栈的特性,即最后入栈的元素最先出栈,同样需要满足队列前端的元素是最后入栈的元素。
2024-07-11 02:30:00
180
原创 双栈实现一个队列
设有含三个元素的栈 A = [1,2,3] 和空栈 B = []。若循环执行 A 元素出栈并添加入栈 B ,直到栈 A 为空,则 A = [] , B = [3,2,1] ,即栈 B 元素为栈 A 元素倒序。B:倒序后,B执行出栈则相当于删除了A的栈底元素,即对应队首元素。因此,可以设计栈A用于加入队尾操作,栈B用于将元素倒序,从而实现删除队首元素。
2024-07-10 22:06:07
258
原创 力扣之有序链表去重
如果 p2 与 p3 的值重复,那么 p3 继续后移,直到找到与 p2 不重复的节点,p1 指向 p3 完成删除。如果 p2 与 p3 的值不重复,p1,p2,p3 向后平移一位,继续上面的操作。p2 为 null 的情况,比如链表为 1 1 1 null。p1 是待删除的上一个节点,每次循环对比 p2、p3 的值。p1.val == p2.val 那么删除 p2。p2 或 p3 为 null 退出循环。当 p2 == null 退出循环。
2024-07-10 21:07:19
1246
原创 Java自己实现动态数组
数组是由一组元素(值或变量)组成的数据结构,每个元素有至少一个索引或键来标识。的,所以数组中元素的地址,可以通过其索引计算出来。尾部位置,时间复杂度是 O(1)(均摊来说)头部位置,时间复杂度是 O(n)中间位置,时间复杂度是 O(n)
2024-07-10 19:41:19
230
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人