<?xml version="1.0" encoding="utf-8" ?><rss version="2.0"><channel><title><![CDATA[zrwcnm的博客]]></title><description><![CDATA[]]></description><link>https://blog.youkuaiyun.com/zrwcnm</link><language>zh-cn</language><generator>https://blog.youkuaiyun.com/</generator><copyright><![CDATA[Copyright &copy; zrwcnm]]></copyright><item><title><![CDATA[畅言社区（论坛系统）测试报告]]></title><link>https://blog.youkuaiyun.com/zrwcnm/article/details/148283654</link><guid>https://blog.youkuaiyun.com/zrwcnm/article/details/148283654</guid><author>zrwcnm</author><pubDate>Wed, 28 May 2025 14:34:07 +0800</pubDate><description><![CDATA[项目介绍测试用例设计部分功能测试示例测试总结。]]></description><category></category></item><item><title><![CDATA[chatroom测试报告]]></title><link>https://blog.youkuaiyun.com/zrwcnm/article/details/148283594</link><guid>https://blog.youkuaiyun.com/zrwcnm/article/details/148283594</guid><author>zrwcnm</author><pubDate>Wed, 28 May 2025 14:32:09 +0800</pubDate><description><![CDATA[项目介绍测试用例设计部分功能测试用例测试总结。]]></description><category></category></item><item><title><![CDATA[数据链路层相关知识]]></title><link>https://blog.youkuaiyun.com/zrwcnm/article/details/145186289</link><guid>https://blog.youkuaiyun.com/zrwcnm/article/details/145186289</guid><author>zrwcnm</author><pubDate>Thu, 16 Jan 2025 16:56:25 +0800</pubDate><description><![CDATA[我们在这⾥介绍ARP协议, 但是需要强调, ARP不是⼀个单纯的数据链路层的协议, ⽽是⼀个介于数 据链路层和⽹络层之间的协议。最理想的情况下, MSS的值正好是在IP不会被分⽚处理的最⼤⻓度(这个⻓度仍然是受制于数据链路 层的MTU).源地址和⽬的地址是指⽹卡的硬件地址(也叫MAC地址), ⻓度是48位,是在⽹卡出⼚时固化的;在⽹络通讯时,源主机的应⽤程序知道⽬的主机的IP地址和端⼝号,却不知道⽬的主机的硬件地址;最⼤值1500称为以太⽹的最⼤传输单元(MTU),不同的⽹络类型有不同的MTU;]]></description><category></category></item><item><title><![CDATA[网络原理初识]]></title><link>https://blog.youkuaiyun.com/zrwcnm/article/details/143694002</link><guid>https://blog.youkuaiyun.com/zrwcnm/article/details/143694002</guid><author>zrwcnm</author><pubDate>Tue, 12 Nov 2024 21:12:07 +0800</pubDate><description><![CDATA[都必须共同遵从的一组约定，规则，如怎么样建立连接，怎么样互相识别，只有遵守这个约定，计算机之间才能相互通信交流。端⼝号是0~65535范围的数字，在⽹络通信中，进程可以通过绑定⼀个端⼝号，来发送及接收⽹络数据。TCP/IP通讯协议采⽤了5层的层级结构，每⼀层都呼叫它的下⼀层所提供的⽹络来完成⾃⼰的需求。在代码中，类似于定义好⼀个接⼝，⼀⽅为接⼝的实现类（提供⽅，提供服务），⼀⽅为接⼝的使⽤。完成两个相邻的设备之间如何进行通信的，通过网线，把电脑和路由器/交换机，相邻节点/设备。]]></description><category></category></item><item><title><![CDATA[HashTable, HashMap, ConcurrentHashMap 之间的区别]]></title><link>https://blog.youkuaiyun.com/zrwcnm/article/details/143571514</link><guid>https://blog.youkuaiyun.com/zrwcnm/article/details/143571514</guid><author>zrwcnm</author><pubDate>Wed, 06 Nov 2024 15:46:35 +0800</pubDate><description><![CDATA[读操作没有加锁(但是使⽤了 volatile 保证从内存读取结果), 只对写操作进⾏加锁. 加锁的⽅式仍然 是使⽤ synchronized, 但是不是锁整个对象, ⽽是 "锁桶" (⽤每个链表的头结点作为锁对象), ⼤⼤降 低了锁冲突的概率.读操作没有加锁. ⽬的是为了进⼀步降低锁冲突的概率. 为了保证读到刚修改的数据, 搭配了 volatile 关键字.⽬的也是为了降低锁竞争的概率. 当两个线程访问的数据恰好在同⼀个段上的时候, 才触发锁竞争.只有两个线程访问的恰好是同一个哈希桶上的数据才出现锁冲突。]]></description><category></category></item><item><title><![CDATA[File和InputStream，OutputStream]]></title><link>https://blog.youkuaiyun.com/zrwcnm/article/details/143521094</link><guid>https://blog.youkuaiyun.com/zrwcnm/article/details/143521094</guid><author>zrwcnm</author><pubDate>Tue, 05 Nov 2024 21:43:12 +0800</pubDate><description><![CDATA[InputStream 只是⼀个抽象类，要使⽤还需要具体的实现类。关于 InputStream 的实现类有很多，基本可以认为不同的输⼊设备都可以对应⼀个 InputStream 类，我们现在只关⼼从⽂件中读取，所以使⽤ FileInputStream// break;// }break;i < n;i++) {1.打开  try with resource2.读read3.关闭 ClosableOutputStream 同样只是⼀个抽象类，要使⽤还需要具体的实现类。]]></description><category></category></item><item><title><![CDATA[线程安全的集合类]]></title><link>https://blog.youkuaiyun.com/zrwcnm/article/details/143416201</link><guid>https://blog.youkuaiyun.com/zrwcnm/article/details/143416201</guid><author>zrwcnm</author><pubDate>Thu, 31 Oct 2024 21:13:19 +0800</pubDate><description><![CDATA[如果修改同一个链表上的两个元素，可能就有线程安全问题，比如把这俩元素插入同一元素后面就可能产生竞争。效率更高，按照桶级别进行加锁，而不是给整个哈希加一个全局锁，有效降低锁冲突的概率。如果修改的两个元素，在不同链表上，本身就不涉及线程安全问题（修改不同变量）服务器代码中的其他逻辑就会读取这些数组/哈希中的值，不会修改。确保读取过程中，要么读到的是旧版数据，要么读到的是新版数据。把旧哈希中的所有元素搬运到新的哈希中（元素很多，耗时很长）服务器就会创建新的数组/哈希，加载新的配置。]]></description><category></category></item><item><title><![CDATA[JUC(java.util.concurrent) 的常⻅类]]></title><link>https://blog.youkuaiyun.com/zrwcnm/article/details/143373679</link><guid>https://blog.youkuaiyun.com/zrwcnm/article/details/143373679</guid><author>zrwcnm</author><pubDate>Thu, 31 Oct 2024 19:45:20 +0800</pubDate><description><![CDATA[JUC(java.util.concurrent) 的常⻅类。]]></description><category></category></item><item><title><![CDATA[CAS的ABA问题]]></title><link>https://blog.youkuaiyun.com/zrwcnm/article/details/143349728</link><guid>https://blog.youkuaiyun.com/zrwcnm/article/details/143349728</guid><author>zrwcnm</author><pubDate>Tue, 29 Oct 2024 22:09:30 +0800</pubDate><description><![CDATA[什么是 CASCAS: 全称Compare and swap，字⾯意思:”⽐较并交换“，⼀个 CAS 涉及到以下操作：我们假设内存中的原数据V，旧的预期值A，需要修改的新值B。1.⽐较 A 与 V 是否相等。（⽐较）2.如果⽐较相等，将 B 写⼊ V。（交换）3.返回操作是否成功。判定内存中的值和寄存器1的值是否一致如果一致，就把内存中的值和寄存器2进行交换但是只关心交换后内存中的值，不关心寄存器2的值此处可以把这样的操作理解成赋值本质上是交换，基于交换实现了赋值。]]></description><category></category></item><item><title><![CDATA[常见的锁策略]]></title><link>https://blog.youkuaiyun.com/zrwcnm/article/details/143274477</link><guid>https://blog.youkuaiyun.com/zrwcnm/article/details/143274477</guid><author>zrwcnm</author><pubDate>Sun, 27 Oct 2024 22:12:53 +0800</pubDate><description><![CDATA[如果后续有其他线程来竞争该锁(刚才已经在锁对象中记录了当前锁属于哪个线程了, 很容易识别当前 申请锁的线程是不是之前记录的线程), 那就取消原来的偏向锁状态, 进⼊⼀般的轻量级锁状态.假设三个线程 A, B, C. A 先尝试获取锁, 获取成功. 然后 B 再尝试获取锁, 获取失败, 阻塞等待;公平锁: 遵守 "先来后到". B ⽐ C 先来的. 当 A 释放锁的之后, B 就能先于 C 获取到锁.如果获取锁失败, ⽴即再尝试获取锁, ⽆限循环, 直到获取到锁为⽌. 第⼀次获取锁失败, 第⼆次的尝试。]]></description><category></category></item><item><title><![CDATA[Java【多线程】定时器]]></title><link>https://blog.youkuaiyun.com/zrwcnm/article/details/143272394</link><guid>https://blog.youkuaiyun.com/zrwcnm/article/details/143272394</guid><author>zrwcnm</author><pubDate>Sun, 27 Oct 2024 20:30:47 +0800</pubDate><description><![CDATA[定时器也是软件开发中的⼀个重要组件. 类似于⼀个 "闹钟". 达到⼀个设定的时间之后, 就执⾏某个指定 好的代码.包含两个参数. 第⼀个参数指定即将要执⾏的任务代码, 第⼆个参数指定多⻓时间之后。标准库中提供了⼀个 Timer 类. Timer 类的核⼼⽅法为。和线程池一样，timer中也包含前台线程阻止进程结束。4.额外创建一个线程，负责执行队列中的任务。2.定时器中，能够管理多个任务的。1.创建一个类，表示一个任务。3.实现schedule方法。核心还是重写run方法。把任务添加到队列即可。]]></description><category></category></item><item><title><![CDATA[Java【多线程】线程池]]></title><link>https://blog.youkuaiyun.com/zrwcnm/article/details/143254799</link><guid>https://blog.youkuaiyun.com/zrwcnm/article/details/143254799</guid><author>zrwcnm</author><pubDate>Sun, 27 Oct 2024 18:28:01 +0800</pubDate><description><![CDATA[（选择使用数组/链表，指定capacity，指定是否要带有优先级/比较规则，线程池，本质上也是生产者消费者模型，调用submit就是在生产任务，线程池里的线程就是在消费任务）在Java中，线程池是一种管理和复用线程的机制，可以有效地减少线程创建和销毁的开销，提高程序的性能和资源利用率。（至少有多少个线程，线程池一创建，这些线程也要随之创建，直到整个线程池销毁，这些线程才会销毁）（也是一种设计模式，和单例模式是并列的关系，用来弥补构造方法的缺陷）统一的构造并初始化线程。此时线程池里的线程就会执行这样的任务。]]></description><category></category></item><item><title><![CDATA[信号量（Semaphore）]]></title><link>https://blog.youkuaiyun.com/zrwcnm/article/details/143221608</link><guid>https://blog.youkuaiyun.com/zrwcnm/article/details/143221608</guid><author>zrwcnm</author><pubDate>Thu, 24 Oct 2024 22:47:32 +0800</pubDate><description><![CDATA[信号量是一种用于控制对共享资源访问的同步工具，它允许多个线程同时访问一个资源，但限制了同时访问该资源的线程数量。在 Java 中，信号量由类实现，提供了获取和释放信号量的方法。通过使用信号量，可以有效地管理并发访问的资源，避免资源竞争问题。]]></description><category></category></item><item><title><![CDATA[Java【多线程】阻塞队列]]></title><link>https://blog.youkuaiyun.com/zrwcnm/article/details/143166785</link><guid>https://blog.youkuaiyun.com/zrwcnm/article/details/143166785</guid><author>zrwcnm</author><pubDate>Tue, 22 Oct 2024 21:52:21 +0800</pubDate><description><![CDATA[put插入元素的时候判定如果队列满了就进行wait（注意，要在循环中进行wait，被唤醒时不一定队列就不满了，因为同时可能是唤醒了多个线程）1.队列为空，尝试出队列，出队列操作就会阻塞，阻塞到其他线程添加元素为止。2.队列为满，尝试入队列，入队列操作就会阻塞，阻塞到其他线程取走元素为止。take取出的时候，判定如果队列为空就进行wait（也是循环wait）此时需要更多的机器进行部署，生产环境的结构会更复杂，管理起来更麻烦。put方法用于阻塞式的入队列，take用于阻塞式的出队列。]]></description><category></category></item><item><title><![CDATA[Java【多线程】单例模式]]></title><link>https://blog.youkuaiyun.com/zrwcnm/article/details/143083944</link><guid>https://blog.youkuaiyun.com/zrwcnm/article/details/143083944</guid><author>zrwcnm</author><pubDate>Mon, 21 Oct 2024 21:35:14 +0800</pubDate><description><![CDATA[线程安全问题发⽣在⾸次创建实例时. 如果在多个线程中同时调⽤ getInstance ⽅法, 就可能导致创建 出多个实例。单例模式（单个实例/对象），就是设计模式中一种非常典型的模式，也是比较简当的模式，还是校招中最容易被考到的设计模式。加锁 / 解锁是⼀件开销⽐较⾼的事情. ⽽懒汉模式的线程不安全只是发⽣在⾸次创建实例的时候. 因。当这个实例创建完了之后, 其他竞争到锁的线程就被⾥层 if 挡住了. 也就不会继续创建其他实例。类加载的时候不创建实例. 第⼀次使⽤的时候才创建实例.]]></description><category></category></item><item><title><![CDATA[Java【多线程】wait和notify]]></title><link>https://blog.youkuaiyun.com/zrwcnm/article/details/143082368</link><guid>https://blog.youkuaiyun.com/zrwcnm/article/details/143082368</guid><author>zrwcnm</author><pubDate>Sat, 19 Oct 2024 20:34:47 +0800</pubDate><description><![CDATA[由于线程之间是抢占式执⾏的, 因此线程之间执⾏的先后顺序难以预知.但是实际开发中有时候我们希望合理的协调多个线程之间的执⾏先后顺序.]]></description><category></category></item><item><title><![CDATA[Java【多线程】volatile关键字]]></title><link>https://blog.youkuaiyun.com/zrwcnm/article/details/142991704</link><guid>https://blog.youkuaiyun.com/zrwcnm/article/details/142991704</guid><author>zrwcnm</author><pubDate>Wed, 16 Oct 2024 21:51:28 +0800</pubDate><description><![CDATA[每个线程，有一个自己的“工作内存”work memory（cpu的寄存器），同时这些线程共享同一个“主内存”main memory 当一个线程循环进行上述读取变量操作的时候，就会把主内存中的数据，拷贝到该线程的工作内存中，后续另一个线程修改，也是先修改自己的工作内存，拷贝主内存里，由于第一个线程仍然在读自己的工作内存，因此感知不到主内存的变化。编译器虽然声称优化操作，是能够保证逻辑不变，尤其是在多线程的程序中，编译器的判断可能出现失误，可能导致编译器的优化，是优化后的逻辑，和优化前的逻辑出现细节上的偏差。]]></description><category></category></item><item><title><![CDATA[Java【多线程】synchronized关键字]]></title><link>https://blog.youkuaiyun.com/zrwcnm/article/details/142989121</link><guid>https://blog.youkuaiyun.com/zrwcnm/article/details/142989121</guid><author>zrwcnm</author><pubDate>Wed, 16 Oct 2024 20:40:12 +0800</pubDate><description><![CDATA[synchronized关键字-监视器锁monitor locker。]]></description><category></category></item><item><title><![CDATA[Java【多线程】线程安全问题]]></title><link>https://blog.youkuaiyun.com/zrwcnm/article/details/142927093</link><guid>https://blog.youkuaiyun.com/zrwcnm/article/details/142927093</guid><author>zrwcnm</author><pubDate>Mon, 14 Oct 2024 21:36:49 +0800</pubDate><description><![CDATA[而是禁止其他线程重新加上这个锁避免其他线程的操作在当前线程的执行过程中插队。反之如果一个代码在多线程并发执行的环境下也不会出现类似于上述的bug。多个线程针对同一个锁对象加锁才会产生互斥（锁冲突/锁竞争）cpu执行这三条指令的过程中，随时可能触发线程的调度切换。2.synchronized()指定的锁对象也得合适。执行任何一个指令的过程中都可能触发上述线程切换操作。当前bug是由于多线程的并发执行代码引起的bug。通过加锁操作让不是原子的操作打包成原子的操作。synchronized(锁对象）{//加锁。]]></description><category></category></item><item><title><![CDATA[Java【多线程】Thread类常见方法]]></title><link>https://blog.youkuaiyun.com/zrwcnm/article/details/142863081</link><guid>https://blog.youkuaiyun.com/zrwcnm/article/details/142863081</guid><author>zrwcnm</author><pubDate>Sat, 12 Oct 2024 23:37:02 +0800</pubDate><description><![CDATA[写了sleep（0）意味着让当前的线程放弃cpu资源（把cpu让出来给别人更多的执行机会，等待操作系统重新调度。当前main这里的方法都执行完了，对应的isFinished就销毁了。因为线程的调度是不可控的所以这个方法只能保证实际休眠时间是大于等于参数设置的休眠时间。在c++的实现中内部就会判断当前是哪个操作系统，并且调用对应系统的api来创建线程。java的Thread对象中提供了现成的变量，直接进行判定，不需要自己创建了。java的做法是，把被捕获的变量给拷贝一份，拷贝给lambda里面。]]></description><category></category></item></channel></rss>