- 博客(45)
- 收藏
- 关注
原创 Quartz的简单使用:实现简单的定时任务
以上示例展示了如何在 Quartz 中配置和调度两个独立的 Job。定义 Job 类:每个 Job 类实现Job接口并定义具体的业务逻辑。配置调度器:为每个 Job 创建JobDetail和Trigger,然后将它们注册到调度器中。启动调度器:调用方法启动调度器,使其开始根据触发器的配置执行 Job。通过这种方式,你可以轻松地管理和调度多个任务。
2024-06-21 13:51:11
438
原创 PageHelper:
PageHelper通过MyBatis的拦截器机制在查询执行前动态修改SQL语句,以便添加分页功能。它极大地简化了分页查询的实现,只需在查询前调用设置分页参数,之后的查询操作将自动应用分页。这种方式不仅避免了手动编写复杂的分页SQL,也使代码更加简洁和可维护。
2024-06-15 11:57:38
1299
原创 java实习--Day02:
然后就是晚上要求交周报,可能由于公司的不同,有些公司要求是交日报,有些公司是交周报。由于是第一次交周报,没经验、而且就来了两天,因此周报就写了寥寥几句话。后面leader看完周报便提醒我,周报要尽量写清楚,例如:你不能只写一句熟悉公司业务,要具体写熟悉了公司的哪些业务,尽量写清楚一些。第二天leader还是让我开文档熟悉公司业务。下午,leader带着我去跟需求开会,由于第一次听需求,啥也不懂直接一屁股干到大屏下面,导致整个会议两小时都是侧着抬着头看屏幕,因此开会时各位应当坐的里显示大屏远一些。
2024-06-09 16:13:54
217
原创 java实习--Day01
办理好入职手续后,大概就是我小组的leader安排我坐在一个空的工位上,leader很热情,先是给我发了一堆账号,让我登录,由于当时组内很忙,leader也没时间管我,于是就给了一份公司业务文档让我先熟悉业务,后续又给了一份项目代码给我熟悉。然后,组内的大哥们就在那讨论业务和敲代码,我就被晾在一旁看文档和代码了。
2024-06-08 20:20:08
381
原创 jstat、jmap、jstack的区别
总的来说,jstat用于监视虚拟机的统计信息,jstack用于生成线程堆栈快照,而jmap用于生成堆转储文件,每个工具都有其特定的用途和作用范围。: jmap主要用于生成Java堆的转储文件(heap dump),可以用于分析Java应用程序的内存使用情况,帮助发现内存泄漏等问题。: jstack主要用于生成Java虚拟机线程快照,可以用于查看Java应用程序中线程的堆栈信息,帮助诊断线程相关的问题,比如死锁。: jstat主要用于监视Java虚拟机的统计信息,包括类加载、垃圾回收、编译等方面的信息。
2024-05-06 21:56:04
2326
2
原创 ThreadLocal:
当我们储存线程本地数据的时候,会以threadlocal作为map的key值,传入的值作为value存入threadlocalmap当中。但是我们需要注意的是map当中的key指向threadlocal的引用是弱引用,而map当中的value指向数据的引用是强引用,也就是说如果threadlocal引用消失之后,threadlocal对象就会被GC回收,而value的值则不会,因为线程对象还存在。ThreadLocal是一个类,他能够为线程存储线程本地变量,这种变量是线程独有的,不会影响其他的线程。
2024-05-06 16:16:21
191
原创 TCP可靠传输:
奇偶检验:就是发送方和接收端设定一个规定,规定传输的信息数据当中的“1”的个数是奇数个或者是偶数个,并在发送端TCP报文段附加位上补上1或者是0,使得数据满足数据中1的个数是奇数个或者是偶数个的要求。这样如果数据在传输过程当中部分的数据编码发生的异变,接收端就能够及时的发现错误。当如果以这种方式作为校验方式有一定的误差,有可能数据段上同时有两位数据发生了异变,那么接收端就无法判断数据传输过程中出现了错误。
2024-05-05 23:33:33
1862
2
原创 使用 fork() 系统调用创建一个子进程时,子进程会继承父进程的什么信息?
但是这样就会产生问题:如果父进程不调用wait或waitpid的话,那么保留的信息就不会被释放,其进程号就会被一直占用,但是系统所能使用的进程号是有限的,如果大量产生僵死进程,将因没有可用的进程号而导致系统无法产生新的进程,这就是僵尸进程的危害。,是指一个进程使用fork函数创建子进程,如果子进程退出,而父进程并没有调用wait()或者waitpid()系统调用取得子进程的终止状态,那么子进程的进程描述符仍然保存在系统中,占用系统资源,这种进程称为僵尸进程。父进程对某文件加了把锁,子进程不会继承这把锁。
2024-05-05 20:29:29
654
原创 ID自增策略:
Leaf是美团开源的分布式ID生成器,能保证全局唯一,趋势递增,但需要依赖关系数据库、Zookeeper等中间件。人为系统将时间进行回拨,要使得多台机器进行同步,需要等待时间慢的机器就需要进行时间回拨。占用10bit,其中高位5bit是数据中心ID,低位5bit是工作节点ID,做多可以容纳1024个节点。占用12bit,每个节点每毫秒0开始不断累加,最多可以累加到4095,一共可以产生4096个ID。雪花算法,它是Twitter开源的由64位整数组成分布式ID,性能较高,并且在单机上递增。
2024-05-04 22:43:10
313
原创 操作系统复习DAY06--文件管理、内存映射文件
因此这里引入了索引节点,在索引节点的目录项当中我们只储存文件名和索引节点的指针,只有当文件是我们所需要的文件时我们才会将索引节点的信息传入内存当中,索引节点当中储存了文件的各种信息。在传统的文件访问当中,一个进程如果需要访问一个文件,首先需要进程从磁盘当中将文件当中所需要的数据读取到进程的虚拟内存空间当中,然后如果对数据进行了修改,那么便需要现在内存当中修改数据,然后再将更新之后的值手动指令加载进磁盘当中。每个文件都有自己的FCB,需要注意的是目录也是一种特殊的文件。我们常见的.txt文件就是无结构文件。
2024-05-04 22:40:32
465
原创 JWT(token):
alg:指定signature采用的加密算法,默认是HS256,对称加密(加密和解密的密钥相同)JWT登出的实现:用黑名单,但这个违背了JWT无状态的初心,但没有其他更好的办法。设置一个secretKey,通过将前两个结果合并后进行HS256算法。secreKey一定不能暴露,因为可以颁发token,也可以解密。默认携带iat,令牌签发时间(时间戳)通过base64Url算法进行编码。通过base64Url算法进行编码。typ:固定值,通常是JWT。exp设置令牌过期时间。
2024-05-03 23:33:18
274
原创 操作系统复习:DAY05--段页式管理,虚拟内存管理
我们所玩的游戏就是如此,一个大一点的游戏就有几十个G,而我们电脑的内存只有8G或者是16G无法将全部的游戏数据全部加载进内存当中,因此这里使用的就是虚拟内存技术,只是将一部分CPU运行需要的数据加载进了内存当中,当需要其他数据资源的时候,才会将新数据加载进内存当中。在之前的32位CPU架构中,内存管理使用的是段页式管理,因此需要先通过逻辑地址中的段号对照段表求出线性地址,然后根据逻辑地址当中的页表+页号对照页表项页表和页内偏移地址求出数据的物理地址。这是最常用的实现虚拟内存的技术。
2024-05-03 23:31:35
1385
原创 GET请求和POST请求之间的区别:
缓存上:浏览器会对GET请求得数据进行缓存,如果浏览器对同一个URL进行GET访问时,第二次会直接从缓存中获取数据。而POST没有缓存。数据传输的方式:GET是放在URL路径?后面的每个参数用&进行连接,具有大小限制。而POST数据是放在请球体里面的,没有大小限制。安全性:GET请求是明文的,而POST请求中的数据放在请求体里面,相对来讲更加的安全。GET和POST都是HTTP协议中最常用的两种请求方式。
2024-05-02 23:19:22
42
原创 操作系统复习DAY04 --内存管理连续分配、基本分页管理
静态重定位:在编译过后得到的可执行文件当中的数据地址还是逻辑地址,但当这些可执行文件加载进内存后,数据地址便会进行重定位,也就是会为数据地址加上内存的初始值。(这种方式,需要操作系统为其分配完整连续的内存,不能够进行分割,因为不同的模块存在不同的地址上时,模块的初始地址就不一样了,那么在加载进内存时逻辑地址转换位物理地址的时候,初始地址就无法正确确定)然后执行指令2,根据指令2当中的类型参数,判断该指令是加法指令,便会让CPU寄存器当中的值也就是x与相对应的值1进行相加,并将结果写进寄存器。
2024-05-02 23:17:44
830
1
原创 ==和equals的区别:
而equals是Object类的一个方法,由于所有得java类都继承了Object类,因此所有的类都拥有equals方法。在没有重写equals方法的情况下,equals方法底层调用的其实也是==,来判断对象是否相等,也就是利用两个对象在对空间中的地址是否相同来判断。==是一种运算符,当==在比较基本数据类型的时候会直接比较那些数据的值是否相等,如果值相等则返回true,否则返回false。当==在比较引用类型的时候,会比较两者在堆中的地址是否相同,相同则返回true,否则返回false。
2024-05-01 23:10:59
61
1
原创 hash冲突的解决方案
双重哈希法,就是在原始的hash函数之上,再增加一个hash函数原来计算探测步长,第二个hash函数必须与第一个hash函数不同,同时要求探测步长不能是0。两种方法的比较: 插入过程中,开放地址法是先计算出hash值,然后依次寻找其他空白的位置,而hashmap是先计算出hash值,然后将其插入所对应的链表之中。查找过程中,开放地址法是先计算出hash值,若在该位置为寻找到对应的值,便会依次寻找其他位置,直到寻找到值,而hashmap是先计算出hash值,然后在对应的链表之中寻找。
2024-05-01 22:59:18
102
1
原创 HashMap的并发问题
在扩容时,会首先创建一个长度是原来数组长度两倍的数组,然后在通过transfer()方法,首先将原来map中桶中的元素都重新hash一遍得到新的hash值,然后将元素放入到新数组对应的数组下标当中。然后,第一个线程接着执行,首先会将A放到第一个线程创建新数组当中,然后再接着将B放入新数组当中,执行到这个时候,e就指向了A,next指向了null,而数组桶中的第一个元素就是B,接着A的next指针便就会指向桶中第一个元素也就是B,那么此时循环就形成了A的next指向B,B的next指向A。
2024-05-01 22:58:25
247
1
原创 操作系统复习--DAY03 调度
中级调度(内存调度):由于系统的内存有限,因此有可能会将一些处于内存当中的进程由内存当中放入外存当中,当CPU需要执行的时候再从外存当中将该进程的信息从外存当中加载进内存当中。被放入外存当中的进程会处于挂起的状态,由挂起队列连接这些被挂起的进程。高级调度(作业调度):面向作业而言,由于操作系统的内存有限,因此无法所有的任务都加载进内存当中,因此只能够将部分作业或者说是任务加载进内存当中,然后创建进程。进程切换:将原来的进程的上下文储存进PCB当中,将新进程的上下文加载进CPU当中。
2024-04-30 23:05:47
230
原创 操作系统复习:DAY02--进程、线程
于是A进程向B进程发送的msg便会进入B进程PCB块中的消息队列当中,B进程然后便可以使用原语receive(A,&msg)接收到A进程发送过来的消息msg。间接通信方式:进程A中创建msg,然后使用原语send(M,msg)往信箱M中发送消息msg,之后进程B便能够使用原语,receive(A,&msg)从信箱M中接收到消息。一个父进程会给自己的子进程分配一定的资源,这些进程与进程之间的资源关系就是树形的结构。:包括进程使用的内存空间分配情况,如基址、界限寄存器的值,或页表信息等。
2024-04-30 23:02:49
1676
1
原创 HTTPS的执行流程:
然后开始TLS进行握手,浏览器首先向服务器发送自己所采用的TLS协议的版本是1.2还是1.3的,一般情况下都是1.3版本的,以及自己所支持的密码套件。此时客户端会对证书的合法性进行验证,比如:证书是否过期、发放该证书的CA是否可靠,证书上的域名是否和实际域名一致等。服务端收到客户端的消息后,首先发送了一个消息告诉客户端自己所要使用的TLS协议版本,以及密码套件是哪一个。然后服务器紧接着又会将自己的证书发送给客户端,该证书中包含了自己非对称密钥中的公钥。至此,客户端和服务端都具有了对称加密中的公钥。
2024-04-29 16:52:53
553
原创 MyBatis中 #{ } 和 ${ } 区别:
{ }是先用占位符代替参数,在对SQL进行编译,然后再将SQL语句中的参数替换进来,这样由于SQL已经经过了编译,因此外界无法通过非法参数进行修改数据库。因此#{}可以避免SQL注入。${ }则是先将参数替换括号,在进行编译,因此当传入参数含有一些带有SQL语句的字符的时候也会参与编译。
2024-04-29 15:31:36
308
原创 TCP的三次握手和四次挥手:
TCP三次握手用于客户端和服务端建立连接的过程。首先客户端向服务端发送标识位SYN=1,以及一个随机的序号seq= x。发送完后,客户端进入SYN—SEND状态,也就是同步已发送状态。服务器接收到客户端的数据包后,向客户端发送标识位SYN = 1,ACK = 1,以及随机序号seq = y,确认号ack = x + 1;发送完后服务端进入SYN_RCVD状态,也就是同步已接受状态。客户端接收到服务器的反馈之后,再向服务器发送标识位ACK = 1,以及确认号ack = y + 1。
2024-04-29 00:06:54
1223
原创 TCP和UDP的区别:
TCP(Transmission Control Protocol,传输控制协议)和 UDP(User Data Protocol,用户数据报协议)都是传输层的协议,都是将数据从源主机发送到目的主机当中的。连接方式不同:tcp是面对连接的协议,要求在发送数据时,要先建立一条从源主机到目的主机之间的连接,然后才能够进行数据的传递。应用场景:TCP用于对数据可靠性高的场景,比如:文件下载,网页浏览、邮件等。数据包大小不同:TCP的数据包通常情况下是没有限制的,而UDP的数据包通常是不能超过64KB的数据的。
2024-04-29 00:04:37
375
原创 DNS(Domain Name System)域名解析系统:
顶级域名服务器便会将下一级域名服务器返回给本地域名服务器,然后依次直到找到能解析该域名的服务器,并返回相对应的ip。根域名服务器便会将该域名所属的顶级域名服务器返回给本地DNS服务器。这里浏览器只需要向本地DNS服务器发送一次请求,无需关注后续的过程,因此浏览器和本地DNS服务器之间是递归的过程。如果本地host文件中没有,则直接向本地DNS服务器发送查询请求,如果本地服务器能够解析该域名,便会直接返回。当我们需要访问一个网页的时候,会首先检查浏览器缓存中是否存在在该域名的ip地址,如果有则直接返回。
2024-04-29 00:00:31
321
原创 TCP/IP五层协议栈:
发送方TCP就把紧急数据放在本报文数据的最前面,紧急数据后面仍然是普通数据,配合紧急指针字段使用,表示 紧急数据到哪里结束。SYN(同步):在建立连接时使用来同步序号,当SYN = 1 ,而ACK = 0 时,表明这是一个请求连接报文, 如果对方同意连接,则在响应的报文段中使SYN = 1 和 ACK = 1。TCP/IP是互联网数据传输协议,它不仅仅是TCP、IP这两种协议,而是一组网络协议,除了tcp、ip这两种还有其他的协议比如:UDP,FTP等。应用层:负责两个主机之间程序之间的通信,产生数据。
2024-04-28 23:58:10
437
1
原创 复习操作系统:DAY01--用户态和内核态
内核态------》用户态:在执行用户态程序前,CPU会执行一条修改PSW状态的指令,将CPU状态转变为用户态(开机完后打开软件)而这些指令,可以分为两种,一种是特权指令、另一种是非特权指令。当前的用户程序需要进行一些内核的操作,因此执行了一条陷入指令(非特权指令),主动的将CPU转变为内核态。在CPU设计和生产的时候就已经划分了特权指令和非特权指令,因此在CPU执行指令的时候就已经能够判断指令的类别。用户态指的就是CPU处于处理用户程序的时期,在该时期内CPU只能够执行非特权指令,不能够执行特权指令。
2024-04-28 23:54:30
467
原创 使用Proteus模拟(Arduino )LED 闪烁程序
现在,我们将仿真电路画好了,下一步需要的就是将十六进制文件从Arduino IDE上传到Proteus。(这里的话注意要首先向组件库中引入Arduino库,不然在组件库中会搜寻不到Arduino UNO板)我这里仿真的是示例中的 LED 闪烁程序。
2024-04-28 18:06:37
614
原创 SpringBoot中内置Web服务器的过程:
在创建SpringBootApplication对象阶段有一个步骤是根据classpath下存不存在该对应的类来推断web服务的类型,他首先是判断是否为REACTIVE类型(响应式编程),然后判断是否为NONE类型(不属于web服务),如果都不是上述两者那么就是属于servlet这种web服务了。由于我们引入了spring-boot-stater-web这个依赖,没有引入REACTIVE相关的依赖所以,最后的web服务类型就是Servlet这种服务类型。
2024-04-27 15:12:55
282
2
原创 Spring中的循环依赖问题:
假设先现在有两个A类和B类,A类依赖于B类,B类依赖于A类。当我们创建A类对象的时候,首先A类实例化出A对象并将其放入第三级缓存当中,然后开始注入B对象时,发现B对象还未创建,于是实例化B对象,然后初始化B对象,然后从第三级缓存中查找到A对象,并将A对象从第三级缓存移到第二级缓存中,然后将不完整的A对象注入B对象,至此B对象完全创建被放进第一缓存,之后再将B对象注入到半成品的A对象当中,至此A对象已完成创建被放入第一级缓存当中。首先构造器层面的循环依赖是无法解决的。
2024-04-27 15:12:02
118
原创 SpringMVC执行流程:
在执行适配器执行controller方法前,会首先执行HandlerExecutionChain对象的applyPreHandler方法,这个方法会遍历执行拦截器方法,如果其中一个拦截器返回了false,那么请求便会直接执行拦截器的afterComletion方法,然后将请求返回,也就是只有所有的拦截器都返回true时,程序doDispatch()方法里面才会执行HandlerAdapter对象的handler()方法来执行controller方法。:根据配置文件中的URL映射来进行请求和处理器的匹配。
2024-04-27 15:09:34
370
原创 Mybatis的执行流程:
二级缓存:是Mapper级别上的缓存,这个缓存默认是关闭的,需要手动开启。只要是同一个Mapper,那么不同的SqlSession也能够生效,缓存中的数据都能被访问到。一级缓存:是SqlSession级上的缓存,是Mybatis中自带的缓存,且无法关闭。:读取 MyBatis 配置文件(通常是 mybatis-config.xml),该文件包含了 MyBatis 的全局配置信息,如数据库连接信息、类型别名、插件等。一级缓存通常情况下是线程独享的,而二级缓存是线程共享的。替换为实际的 SQL 语句。
2024-04-27 15:01:51
331
原创 MySQL慢查询:
我们可以开启mysql的慢查询日志,慢查询日志默认是关闭的,需要手动开启。const — 将一个主键放置到 where 后面作为条件查询, MySQL 优化器就能把这次查询优化转化为一个常量,如何转化以及何时转化,这个取决于优化器,这个比 eq_ref 效率高一点。possible_keys 是 idx_age,表示可能会被使用的索引。select_type 是 SIMPLE,表示这是一个简单的查询。key 是 idx_age,表示实际使用的索引。key_len 是 4,表示使用索引的长度。
2024-04-27 14:55:46
253
原创 Redis中的大key问题
所谓的大key就是指,在redis当中有一些key对应的value值很大,用几个实际的例子对大Key的特征进行描述:● 一个String类型的Key,它的值为5MB(数据过大);● 一个List类型的Key,它的列表数量为20000个(列表数量过多);● 一个ZSet类型的Key,它的成员数量为10000个(成员数量过多);● 一个Hash格式的Key,它的成员数量虽然只有1000个但这些成员的value总大小为100MB(成员体积过大);
2024-04-27 14:52:52
175
原创 Redis当中热门key问题:
四:monitor命令,能够实时的抓取到redis接收到的请求然后通过分析工具进行分析。或者是redis cli -hotkey命令也能够进行获取到热门key。二:将热点key进行备份,然后将备份的key放入其他集群的主机当中。一:由运营者根据自身的经验,对商品进行预测,预测哪些是热门数据。三:自己写抓包程序监听相对应的端口,然后解析redis访问请求。一:使用JVM二级缓存,先在JVM二级缓存中获取到数据。二:在代码中加入统计访问量的代码。
2024-04-27 14:50:41
200
原创 Redis当中容易出现的安全问题(雪崩、穿透、击穿):
产生原因: 第一个:在设置键过期时间的时候,刚好设置的相同的过期时间,导致大量的键值同时过期 第二个:缓存服务器出现故障,无法提供服务 解决方法: 第一个:在设置键的过期时间的时候,设置随机的过期时间防止大量的键同时过期。解决方法: 一:布隆过滤器:在查询请求到达时,直接判断数据库中是否含有该值,若无,则直接返回错误 二:返回空值,如果数据库和缓存中都不存在访问值,那么在缓存中将该键对应的值设为空值 三:请求限流,对于一些恶意的请求,直接返回错误。缓存击穿指的是热门数据过期,导致大量请求访问数据库。
2024-04-27 14:46:27
464
原创 Redis的删除策略:
Redis的删除策略是指在设置了过期时间的键上,在某种条件之下触发的自动删除过期的键。删除策略有两种:第一种是定时删除策略:也就是设置了过期时间的键当已经到过期时间的时候,定时器立即删除该键,无论CPU负载有多大。(以时间换空间)第二种是懒汉式删除策略:也就是在访问该键时,我们才去判断该键是否过期,若过期则直接删除。(以空间换时间)第三种是定期删除策略(定时任务方式):也就是定期的从redis所有键中随机的抽取一部分设置了过期时间的键,然后将这些键当中已经过期了的删除。
2024-04-27 14:43:04
388
原创 Redis当中的String类型
redis通常是key-value结构,key可以是字符串,数字等其他结构,但一般是字符串类型。而value可以是string、set、zset、hash、list,但通常我喜欢使用string类型,通常会首先将对象进行序列化成字符串,然后再存进redis中。embstr:是在字节长度比较小的是时候使用的,内存分配次数只会分配一次,释放也只会释放一次。但这种编码方式是只可读的,也就是在修改字符串时需要先将编码格式转变为raw,在执行修改命令,重新为字符数组分配空间。因此不会出现溢出的情况。
2024-04-27 14:40:49
331
1
原创 为什么重写equals方法的时候必须重写hashcode方法:
一般我们在比较数据对象是否相同的时候,习惯的喜欢先使用对象的hashcode()方法来比较,两对象的hash值是否相同,如果两个对象的hashcode()后的hash值都不相同,那么这两个对象就一定不是同一个对象,如果两对象的hashcode值相同,则还需要使用equals()方法来比较两对象,如果equals()方法比较后两者的值还是相同的,那么就代表这两个对象相同。但hashcode()后得到的得值相同,这两对象有可能相同,有可能不同,还需要是equals()来比较。
2024-04-27 00:31:59
156
1
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人