- 博客(33)
- 收藏
- 关注
原创 TCP的“可靠性”(下)——三次握手四次挥手
完全可以有一个数据包,第五位和第二位都是 1,此时这个数据包就同时起到了两个作用,既能够应答上个请求,也能发起 syn。这个操作实际上在第一次握手的时候就完成了,但是最终确立出这个连接要建立,确立出后续要进行通信,还是得所有的流程都走完)如果实际通信过程中,ack 和第二个 fin 时间间隔比较长,此时就无法进行合并了,就分成两次来传输。等到终于到了对端的时候,已经改朝换代了,之前的连接早都没了,现在是新的连接了!第一次连接的过程中,传输的有一个数据包,在路上堵车了,迟迟没有到达对端。
2024-12-05 19:05:39
1539
原创 TCP的“可靠性”(上)
整个网络中,就可能存在,某个路由器/交换机,某个时刻,突然负载量很高,短时间内可能有大量的数据包要几个这个设备转发。这个时候,如果瞬间的高负载超出了这个设备能转发的数据量的极限,多出来的部分,就无了,就被设备丢包了。上述谈到的,ack,重传,保证顺序,自动去重,都是 TCP 内置的。这个说法是很不准确的,因为三次握手四次挥手只有初次建立连接的时候才会,但是可靠性是整个过程都可靠,那靠的什么呢?此处可靠性,只能“退而求其次”,只要尽可能的去进行发送了,发送方能够指定对方是否收到,就认为是可靠传输了。
2024-12-05 18:50:15
1848
原创 TCP连接过程中涉及到的状态转换
TCP 服务器和客户端都要有一定的数据结构来保存这个连接的信息。在这个数据结构中其中就有一个属性叫做 “状态”操作系统内核根据状态的不同,决定了当前应该干什么。(不会迷茫也不会混乱)LISTEN状态,表示服务器这边,创建好 serverSocket 了,并且绑定端口号完成。ESTABLISHED已确立的。客户端和服务器连接已经建立完毕 (三次握手握完了)谁被断开连接,谁进入 CLOSE_WAIT。
2024-12-05 18:18:03
1001
原创 初识TCP(编写回显服务器)
客户端请求到达之后,sanner.hasNext返回,继续执行,读取请求,根据请求计算响应,返回响应给客户端…serverSocket整个程序只有唯一一个对象,并且这个对象的生命周期很长是要跟随整个程序的,这个对象无法提前关闭,只要程序退出,随着进程的销毁一起被释放即可(不需要手动进行)Socket 就如同那个购房洽谈室,是服务器(售楼处)和客户端(购房者)交流互动的专属空间,双方在这里收发信息,像在洽谈室里商量买房的各种事儿一样,完成数据通信。所谓回显服务器就是客户端发起什么请求,就返回什么响应。
2024-12-04 19:46:12
1878
原创 初识UDP(编写一个回显服务器)
服务器往往是7*24小时运行的,要持续不断地运行下去,这里的while(true)也没有退出的必要,如果你确实想重启服务器咋办,可以直接杀进程即可。通过网卡发送数据,就是写socket文件,通过网卡接收数据,就是读socket文件)、接下来要操作网卡,操作网卡都是通过socket对象来完成的(socket对象是在内存中,针对这个内存进行操作就能影响到网卡)想必大家应该听说过 UDP的特点:无连接,不可靠传输,面向数据报,全双工。对于服务器来说,需要不停的收到请求,返回响应,收到请求,返回响应。
2024-12-03 20:51:48
1968
1
原创 初识交换机和路由器
lan口可以有多个,用来连接家庭网络设备,比如台式机,手机,笔记本,其中手机和笔记本是通过WiFi连接到路由器的设备,也相当于连接到了lan口上。如果集线器能智能一点,把信息只发给对的计算机就好了,于是发明了交换机,交换机就是在集线器的基础上更加智能一点了,能把信息只发给对应的 计算机。的设备,有很多接口,当一台计算机A想发消息给计算机B,消息到达集线器,集线器就无脑把信息广播给所有连接它的计算机BCDEF…真实情况下,两个主机不是通过网线直连的,而是通过一系列的交换机或路由器来进行数据转发的。
2024-12-03 19:44:56
2145
1
原创 五层网络协议(封装和分用)
一个协议太复杂太庞大,非常不利于学习和维护,需要把一个高大全的协议,拆分成多个功能更单一,“小而美”的协议。网络通信过程中,需要涉及到的细节,其实是非常非常多的,如果要有一个协议来完成网络通信,就需要约定好方方面面的内容,非常多的细节,导致这个协议非常复杂。【交给下层,指的是,下层协议提供一组API(函数),上层调用这个API,并且把刚才构造好的数据通过参数传过去,下层协议就可以来处理这个数据了】OSI七层网络协议,最初大佬们设计的时候,给出的方案,后来在实施过程中,太麻烦了,就简化成了五层。
2024-12-02 21:58:01
2715
1
原创 ConcurrentHashMap
(创建一个更大的数组,把旧的Hash表的元素都搬运到(删除/插入)新的数组上,如果Hash表本身元素非常多,这里的扩容操作就会消耗很长的时间!比如,服务器加载配置文件的时候,就需要把配置文件的内容解析出来放到内存中的数据结构中,但是服务器的配置文件,修改的频率都很低,而且配置文件一般体积都不大,几KB就已经不小了,所以可以使用这个写时拷贝。一旦有现成要修改这里的值,就要把顺序表复制一份,修改新的顺序表内容,并且修改引用的指向(这个操作是原子的,不需要加锁)充分的使用了CAS原子操作,减少了一些加锁。
2024-11-27 18:36:36
1163
1
原创 ReentrantLock(可重入锁) &Semaphore(信号量) & CountDownLatch
传统的锁的风格,这个对象提供了两个方法: lock unlock 这个写法,就容易引起,加了锁之后,忘记解锁了。下载一个文件,可能很大,但是可以拆成多个部分,每个线程负责下载一部分,下载完成之和,最终把下载的结果拼在一起。后来synchronized变得厉害了,ReentrantLock用的少了,但是仍有一席之地。上古时期的Java中,synchronized不够强壮,功能也不够强大,也没有各种优化。比如,多线程执行一个任务,把大的任务拆分成几个部分,由每个线程分别执行。
2024-11-26 19:26:41
1522
2
原创 基于CAS实现的无锁化编程(面试)
CAS(compare and swap)是一个特殊的CPU的指令。完成的工作,就是“比较和交换”。比较交换的是 内存 和CPU寄存器。借助这个操作,就可以原子的完成很多复杂操作,达到“无锁化编程”效果。但是CAS也不是万能的解药这些操作时通过单个CPU指令来完成的,单个指令就是原子的基于CAS指令给编写线程安全的代码,打开了一个新世界的大门!!之前线程安全都是靠加锁。加锁=>阻塞=>性能降低使用CAS,不涉及加锁,不会阻塞,合理使用也能保证线程安全---------->无锁编程。
2024-11-26 18:19:54
1494
1
原创 Java常见的锁策略
Java中的synchronized就是非公平的(也就是没有按先后顺序)要想实现公平锁,就需要引入额外的数据结构(引入队列,记录每个线程先后顺序)才能实现公平锁。(能记录先后顺序的)使用公平锁,天然就可以避免线程饿死的问题非公平锁:就是每个线程等概率竞争,不遵循先来后到。
2024-11-25 19:33:04
2602
1
原创 手撕一个简单的线程池
某个线程取到了某个任务了,但是并非立即就执行,这个过程中另一个线程就插到前面了。直接写一个固定线程数目的线程池(暂时不考虑线程额增加和减少)一定要注意,多个线程之间的执行顺序是不确定的。此处的这些线程,彼此之间都是等价的。
2024-11-24 20:09:22
1237
1
原创 初识线程池
如果一个进程中,所有的线程都是IO密集型的,每个线程的大部分工作都是在等待IO,CPU消耗非常少。如果一个进程中,所有的线程都是CPU密集型的,每个线程所有的工作都是CPU上执行的。如果创建销毁线程的频率进一步提高,此时线程的创建销毁开销,也就不能无视了!衡量每种线程数目下,总的时间开销,和系统资源占用的开销,找到这两者之间的合适的值。实际上一个进程中的线程,大概率都是一部分是IO,一部分是CPU的。而且从线程池里取线程,是纯用户态代码,(可控的,直接拿)尝试给线程池设定不同的线程数目,分别进行性能测试。
2024-11-24 19:50:35
2016
1
原创 手撕一个计时器
只有一个main线程一个 t 线程,main是添加任务的,t 是扫描队列 负责执行的,不是每个任务一个线程。都要求元素是”可比较大小“不用PriorityBlockingQueue,虽然是线程安全的,但是不好掌控。HashMap,HashSet ,则是要求元素是“可比较相等”“可Hash的”有时候,为了让Hash表更高效,可能需要重写equals和hashCode。用 PriorityQueue,虽然线程不安全,但是可以手动加上锁。有些集合类,是对元素有特定要求的。如何手写一个计时器?
2024-11-24 18:49:39
1517
1
原创 手撕一个阻塞队列
(最核心的部分是阻塞队列,使用synchronized和wait/notify达到 线程安全 &阻塞)了。这里的生产者和消费者往往不仅仅是一个线程,也可能是一个独立的服务器程序,甚至是一组服务器程序。要手撕一个阻塞队列:就要实现一个普通的队列,加上阻塞,加上锁。实际上,生产者消费者模型,往往是多个生产者多个消费者。基于这个阻塞队列,就可以写一个简单的。
2024-11-24 18:22:14
1341
1
原创 饿汉模式和懒汉模式(面试)
如果t2继续使用instance里面的属性或者方法,就会出现问题(此时这里的属性都是未初始化的 “全 0” 值),就可能会引起代码的逻辑出现问题。这个变量的作用是存储这个类的唯一实例。上述代码中,由于t1线程执行完 1) 3) 之后,调度走,此时instance指向的是一个非null的,但是未初始化的对象。指令重排序,是编译器优化的一种方式->调整原有代码的执行顺序,保证逻辑不变的前提下,提高程序的效率。实例是在类加载的时候就创建了,创建时机非常早,相当于程序一启动,实例就创建了。
2024-11-23 20:12:28
2085
1
原创 线程控制方法之wait和sleep的区别
但是由于t2此时还没有释放锁呢,t1 WAITING恢复之后,尝试获取锁,就可能会出现一个小小的阻塞,这个阻塞是由于锁竞争引起的。t2执行完t2 notify之后,释放锁,t2执行完毕,t1的wait就可以获取到锁了,继续执行打印t1 wait之后。接下来打印t2 notify之前,执行notify操作,这个操作就能唤醒t1(此时t1就从WAITING状态恢复回来了)sleep()不释放锁且自动苏醒,用于暂停执行。t2 sleep结束之后,由于t1是wait状态,锁是释放的,t2就能拿到锁。
2024-11-23 19:09:44
1993
1
原创 笔记本电脑一直充不进电怎么办?
拔掉电源,长按开关键30秒(哪怕按了几秒之后已经关机了也要一直按,按30秒!今早上就只有20的电,一直充都还是只有20,充不进去。然后开机,充电,就可以了。
2024-11-17 18:21:14
1563
2
原创 内存可见性引起的线程安全问题
1.load操作执行的结果,每次都是一样的!频繁执行load和 条件跳转 ,load的开销大,并且load 的结果又没有变化(真正出现变化是好几秒之后的事情)。这样可以大幅度提高循环的执行速度。volatile关键字:强制读取内存(开销是大了,效率是低了,但是数据准确性/逻辑的正确性,提高了)访问寄存器的操作速度,远远超过访问内存!此时 JVM 就产生怀疑,怀疑你这里的load操作是否真的有存在的必要?此时JVM就可能作出代码优化,把上述load操作,给优化掉!由于上述循环中,循环执行的速度非常快!
2024-11-17 09:00:31
2659
原创 多线程——使用jconsole观察线程死锁
注意,要运行项目才能看到现象。找到你项目对应的进程,点击连接即可。如果有其他弹窗提示,选择“不安全连接”即可。Thread-0和Thread-1就是我们的线程(或者你也可以自己在代码里面命名线程)在 windows 下我们可以直接找到 JDK 的所在目录,去。我这里使用everything工具找到jconsole。观察线程状态,两个线程在互相等待。我们使用jconsole工具来观察一下。可以看到没有任何输出,出现了死锁。
2024-11-17 08:57:52
2460
原创 一文彻底搞懂线程中断interrupt导致sleep报InterruptException
处理InterruptedException异常时要小心,如果在调用执行线程的interrupt()方法中断执行线程时,抛出了InterruptedException异常,则在触发InterruptedException异常的同时,JVM会同时把执行线程的中断标志位清除,此时调用执行线程的isInterrupted()方法时,会返回false。
2024-11-16 08:53:56
3062
1
原创 多线程——start和run的区别
当前代码中由于是直接调用run方法,会先执行MyThread4类的run方法中的循环,一直打印 “hello,线程” ,直到遇到异常或者循环结束。(通俗来说就是,一个线程start一次了,它的run执行完了或者因为异常终止之后,就进入死亡状态了,它的资源可能都已经释放了或者处于不可以状态了。start方法不能被重复调用,而run方法可以被重复调用,但只是作为普通成员方法,不会创建新的线程。start方法是通过JVM来调用run方法的,而直接调用run方法只会在当前线程中同步执行。
2024-11-16 08:51:54
2721
1
原创 线程创建的5种方式(面试)
Callable是一个“锦上添花”的东西,它能干的事情,使用Runnable也能干。Runnable关注的是这个过程,不关注执行结果。Runnable提供的run方法,Callable要关注执行结果,Callable提供的call方法,的任务,使用Callable会更好一些。代码更直观,更简单。这里不作过多解释,只因为博主也没有深入了解,所以不敢瞎说。上面演示快速上手一个线程就属于继承Thread类。因为所有的方式的本质都是。
2024-11-15 17:09:51
2894
1
原创 初识多线程
运行:可以看到如果不手动终止这个程序,就会无限打印下去。Callable是一个“锦上添花”的东西,它能干的事情,使用Runnable也能干。多线程的随机性是指在多线程编程环境中,多个线程的执行顺序、对共享资源的访问顺序以及它们之间的交互。Runnable关注的是这个过程,不关注执行结果。Callable要关注执行结果,Callable提供的call方法,的任务,使用Callable会更好一些。这种不确定性主要源于操作系统的线程调度机制。要观察这种特性,就要有2个及以上的线程。因为所有的方式的本质都是。
2024-11-15 16:46:07
3113
1
原创 从单体架构到分布式架构的演变历程
原本一个数据库服务器上有多个数据库(这里指的是逻辑上的数据集合,通过 create database 创建的那个东西)。数据库服务器,需要更大的硬盘空间,更快的数据访问速度。将数据区分为 “热数据” 和 “冷数据”,把热点数据放置到缓存中,缓存的访问速度往往比数据库快很多。主服务器一般是一个,从服务器可以有多个(一主多从),同时从数据库通过负载均衡的方式,让应用服务器进行访问。数据库存储的仍然是完整的全量数据。当集群中的某个主机挂了,其他的主机仍然可以承担服务,提高了整个系统的可用性。
2024-11-14 19:44:42
3901
原创 初识Redis
Redis(Remote Dictionary Server)是一个在内存中存储数据的中间件。用于作为数据库,也可以作为数据缓存,在分布式系统中能够大展拳脚。Redis和MYSQL一样也是一个客户端-服务器结构的程序。
2024-11-14 14:34:56
2909
1
原创 swagger、Postman、Test测试都能过,代码没问题但项目仍然不成功
swagger、Postman、Test测试都能过,代码没问题但项目仍然不成功。swagger、Postman、test测试都没问题说明后端代码没问题。那么在前端代码中打日志,发现没运行到相应的位置。清除前端缓存之后就可以了。
2024-11-10 15:34:47
2432
原创 配置拦截器时Bean注入失败的解决方案
如果你发现,修改了,但是在没有登录的情况下还是拦截失败还是可以访问资源,那么有可能是。为什么会注入失败,有没有大佬来解释一下,网上解释我看的也云里雾里的。我就凭感觉改了一下,运行成功了,没有报Bean注入失败。我试了那些解决方法,都没解决。
2024-11-09 12:38:26
2161
原创 mybatis插入数据运行成功但数据库没有数据,id却在增长,是什么原因??
虽然日志显示插入语句执行成功,但可能事务在提交过程中出现了问题。比如在后续的操作中有异常抛出导致。mybatis插入数据运行成功,但是数据库却没有数据,id也在增加。原因:在测试方法上面加了 @Transactional。,而日志只记录了插入语句的执行情况,没有反映出事务回滚的状态。我把@Transactional 删除之后,就能正常插入了。
2024-11-07 16:11:58
2684
1
原创 Error creating bean with name ‘xxx‘和 Error creating bean with name ‘sqlSessionFactory‘以及文档中根元素后面的标记.
(因为这个是mybatis自动帮我生成的文件,所以我就很放心没有仔细去看,没想到竟然被它背刺了啊啊啊啊啊啊啊啊)出现这个问题,可能是SQL语句的xml文件里面写的有问题。比如说我的就多了一个</mapper>删掉这个多余的就行了。
2024-11-07 14:03:54
2449
原创 一文读懂:Session、Cookie与Token
在Web应用中,Cookie是HTTP协议制定的一种会话跟踪技术,它是一个非常具体的东西,指的就是浏览器里面能永久存储的一种数据,仅仅是浏览器实现的一种数据存储功能。Cookie是一种运输信息的工具,在客户端和服务端之间往返运输信息的“小包裹”session翻译过来就是会话,它的主要作用是在用户与服务器交互的过程中,保持用户的状态信息。例如,在用户登录一个网站后,服务器可以使用 Session 来记录用户的登录状态,以便在用户浏览不同页面时,服务器能够识别出该用户已经登录,无需再次输入用户名和密码。
2024-10-17 10:42:40
3032
2
原创 Java-排序算法-复盘知识点
由于 Math.pow 返回的是 double 类型的值,即使你传入的参数是整数,结果也会是 double 类型的。20.Math.pow 是 Java 中的一个静态方法,用于计算第一个参数的第二个参数次幂的值。24.复习大根堆的经典使用场景,看我的主页的《Java中等题-有序矩阵中第k小的元素(力扣)》21. 复习手搓大根堆,可以看我的主页的《Java中等题-数组中的第k个最大元素(力扣)》18.复习一下我的主页里面的《Java中等题-对链表进行插入排序》刷了24道简单排序题,18道中等排序题之后,给。
2024-08-02 17:15:15
2439
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人