03 2020 档案
摘要:I/O 设备是计算机的重要组成部分,介于处理器与 I/O 设备交互的复杂性,I/O 操作一直是高级语言开发者比较难掌握的一个技术点。 因为高级语言对 I/O 操作的封装基于操作系统提供的系统函数,而这些系统函数的调用方式又与其硬件层的结构与工作机制息息相关,所以想要彻底搞懂 I/O 操作的那些函数,
阅读全文
摘要:请求报文 HTTP 请求整体的报文结构由 请求行-请求头-请求数据 三部分构成,其中请求行格式是固定的,标识了请求方法/请求URL和协议版本它们之间用空格间隔。 请求头是我们为请求添加的附加信息,也就是一些额外的控制位。我们可以选择性的为请求添加请求头,除了一种特殊情况,POST 请求时请求头中必须
阅读全文
摘要:HTTP位于五层模型中的应用层,是传输层(代表为TCP协议)的上层协议。 之前我们通过 socket 实现了使用 TCP 协议进行数据收发:手写一个模块化的 TCP 服务端客户端 ,对 TCP 协议的使用有了一个初步的认识。 简单的说,IP 协议 帮助我们的数据包在复杂的网络环境下进行寻址,但并不能
阅读全文
摘要:一个经典的问题,判断某个整数是否为回文数。 问题很简单,练手题。 递归表示,如果某个字符与其回文字符不同,则不是回文数;如果相同,则继续判断其子串是否为回文数: public final boolean isPalindrome(int x) { if(x<0){return false;} if(
阅读全文
摘要:1.1 异常处理 异常的处理应当符合 尽早抛出,延迟捕获 的原则。 在进行 MVC 分层调用时,Service 与 Dao 层触发的异常应统一向上抛出,交给 Controller 层处理。因为只有 Controller 层可以更好的决策发生异常时应当给用户何种反馈。 但这样会造成我们的 Contro
阅读全文
摘要:在实际开发时,许多业务接口的入参非常复杂,比如会有多级的 JSON 嵌套或者混杂着各种数组。 这种时候如果我们将接口参数的拼装逻辑杂乱的写在 Controller 层,代码的可读性会非常差,后续接手的人员需要一个参数一个参数的比对着接口文档来推演参数的拼装逻辑。 在这种情况下,将接口调用参数封装为数
阅读全文
摘要:在使用微服务的过程中,RPC 是永远绕不开的点。之前并没有磕的很深,一直觉着 RPC 是一个黑魔法。比如我们常用的 Dubbo、SpringCloud 等框架,将微服务模块间的方法调用封装的像本地方法调用一样,方便又令人费解。 今天如愿以偿的仿照 Dubbo 自己手写了一个 rpc “框架”,虽然简
阅读全文
摘要:前面的博客 基于 socket 手写一个 TCP 服务端及客户端 写过一个简单的 TCP 服务端客户端,没有对代码结构进行任何设计,仅仅是实现了相关功能,用于加深对 socket 编程的认识。 这次我们对整个代码结构进行一下优化,使其模块化,易扩展,成为一个简单意义上的“框架”。 对于 Socket
阅读全文
摘要:通过 socket 实现一个 TCP 服务端与客户端,实现通过 TCP 协议进行消息收发。 关键在 socket 的使用的理解上。 socket 是对操作系统提供的协议栈的封装,底层调用的是操作系统提供的协议栈。 当我们调用 ServerSocket 的 accept 方法时,线程阻塞。以 TCP
阅读全文
摘要:进行 Socket 编程时经常会碰到 TCP 的粘包与半包问题,很多时候我们选用 netty 等框架而不直接采用原生的 Socket 编程也是因为 netty 帮我们将该类传输过程中可能出现的问题屏蔽掉了,使我们可以抽出更多精力来关注功能的实现,而不是挣扎在处理这些底层问题上。但尽管如此,我们也必须
阅读全文
摘要:动态代理 核心方法为 Proxy.newProxyInstance 方法,该方法需要传入 被代理类的类加载器、被代理类实现的接口 以及一个 InvocationHandler 的实现类实例。 方法会通过字节码技术为我们返回一个代理对象,代理对象会实现被代理对象的所有接口,并在这些接口声明方法前后织入
阅读全文
摘要:代理模式 为其他对象提供一个代理以控制对某个对象的访问。代理类主要负责为委托了(真实对象)预处理消息、过滤消息、传递消息给委托类,代理类不现实具体服务,而是利用委托类来完成服务,并将执行结果封装处理。代理类本身不实现服务,而是通过调用被代理类中的方法来提供服务。 从设计模式上看,代理模式与适配器模式
阅读全文
摘要:了解字节码文件可以让我们从更底层的视角理解 JAVA 的内部运作机制。程序说白了就是一堆逻辑和数据,字节码文件中便存储着可以支撑 JAVA 语言逻辑的数据。 .java 文件经过 javac 编译后会生成一份 .class 字节码文件。.class 文件是 java 跨平台的基础,JVM 对各种操作
阅读全文
摘要:序列化与反序列化的使用场景: 把对象的字节序列永久地保存到硬盘上,通常存放在一个文件中; 在网络上传送对象的字节序列。 面向对象的一大特性便是封装,我们将模型的属性和方法封装到一个类中,非静态属性在对象实例化时被赋予具体的值。 可以这样理解,对象是 JAVA 层面用于描述一个实体的数据结构,与 XM
阅读全文
摘要:适配器模式可以将一个类的接口转换成客户希望的另外一个接口,使得原本由于接口不兼容而不能在一起工作的那些类可以一起工作。 适配器模式是一种对象结构型模式,这里的接口不仅仅是java语言中的interface,更多是指一个类型所具有的方法特征集合,是一种逻辑上的抽象。 客户端需要一个target(目标)
阅读全文
摘要:针对 bootstraptable 中 hiden 为 true 的列 。 隐藏列不会渲染为 DOM 元素,所以我们无法通过 DOM 元素获取。 我们需要通过 bootstraptable 数据源的数据对象获取,其中包含隐藏列的数据。 //获取当前行的 bootstrap 数据对象 getDataR
阅读全文
摘要:当一个事件发生时,当前 DOM 元素本身可能不能处理这个事件,事件必须从这个按钮传播出去,从而到达能够处理这个事件的代码中。事件向上传递的过程便是事件冒泡。这是一个典型的责任链模型,由责任链上的节点依次对事件进行处理。当然,必要的时候我们也可以根据需要禁止事件的传播。 比如,当多个嵌套的 DOM 元
阅读全文
摘要:链表实现: /** * @Author Nxy * @Date 2019/12/4 * @Param * @Return * @Exception * @Description 链表并归排序 * 递归分解序列为两个子序列,并向上并归排序,返回排序后的总链表 * 使用快慢指针法,快指针到终点时慢指针指
阅读全文
摘要:总结:策略模式对对象与行为进行了解耦,增加类的可扩展性,使我们对类的扩展更加符合开闭原则。 忽然对设计模式有了很多感悟,原来对设计模式的学习也费了不少功夫,但始终感觉轻飘飘的,抓不住重点。 最近重构代码的任务比较多,随着对代码结构的重新设计,很多之前不明白的地方忽然就通了。 从优化代码结构的角度出发
阅读全文
摘要:1、开闭原则(Open Close Principle) 开闭原则的意思是:对扩展开放,对修改关闭。在程序需要扩展或修改时,不应直接改变原有代码,而是应该将代码模块化、组件化,对模块进行拔插使用。 比如,一个 TimeUtil ,我们最初编写时将其计时单位设置为了毫秒,后来接到新的需求,需要将计时单
阅读全文
摘要:池化是我们在实际生产中经常用到的一种思想,通过一个 “池” 把资源统一的管理起来。可以达到对资源的合理管理、重复利用、减少资源创建/销毁的开销等目的。 常见的比如常量池、连接池、线程池,今天我们手撸一个线程池。 抛开语言特性,线程池无非是维护一堆线程阻塞等待任务的到来,并由主线程对任务线程的数量进行
阅读全文
摘要:上一篇博客写了分治解法以及为什么要用分治。 分治通过我们对子问题的定义,实例化了我们每一步计算的语义,从而帮助我们找到解空间中的重复结构。 在进行分治时,我们找到了分割问题,并用子问题的解表示问题解的方式,也就是状态转移方程: 整个分治的计算过程分为两个阶段,向下分割问题,向上汇聚子问题的解从而得到
阅读全文
摘要:上一篇博客贴了该题的暴力递归解法,这次贴一下分治解法。 分治法是不断的将问题分解,直到分解到最小子问题,然后不断的向上返回,由小问题的解表示大问题的解。 首先需要了解的是,分治不等于二分,二分法是分治的一个特例。二分法可以直接在每次计算时,将问题规模减半。而普通的分治并没有缩小总的问题规模,只是将问
阅读全文
摘要:首先声明的是这种解法非常非常的原始和不优雅,甚至比暴力递推还要臭长。 对于最长回文子串这种经典的老题目,有很多亮眼的解法,比如与逆序串取交集。 但我们解决问题不能总是依靠这种眼前一亮(虽然很少亮那么一下),我们应该有一些通用的思考方法,可以用来解决绝大部分问题。 问题的解决都有递归和递推的两种描述,
阅读全文
摘要:今天接手了一个新项目,发现框架中有一些点很有意思。 在之前接手的项目中,资源类的请求(比如请求一个页面),都是通过后台接口接收请求参数,再由模板引擎(比如FreeMarker/Thymeleaf 等)将动态数据拼装到静态页面中,再向请求方返回拼装好的页面。 但如果是 get 请求,其请求参数是包含在
阅读全文
摘要:kill 掉一个线程,感觉是一件很简单的事情,比如 JAVA 中为我们提供了 stop 方法可以立即终止线程的执行,达到 kill 掉线程的目的。 但实际上对线程的操作是一件精细活,对于一段正在执行的任务,我们不能只是简单粗暴的勒令其停止。原因就是,线程与资源是有关联的。 比如,一个线程持有某个 l
阅读全文
摘要:看题目: 第一种解法采用绝对悲观锁保证绝对的线程安全,思路很简单:不考虑线程协作写代码,然后找出单线程环境下存在控制依赖与数据依赖且涉及共享变量的部分,保证其原子性后确定互斥关系,决定那些操作是互斥的,则共用一把锁。 class H2O { int hNums=0; int oNums=0; pub
阅读全文
摘要:首先认识一下 CAS:CAS是支持并发的第一个处理器提供原子的测试并设置操作,通常在单位上运行这项操作。操作数为V,A,B。 CAS 操作包含三个操作数 —— 内存位置(V)、预期原值(A)和新值(B)。如果内存位置的值与预期原值相匹配,那么处理器会自动将该位置值更新为新值。否则,处理器不做任何操作
阅读全文
摘要:先吐槽一下网上对原子性的解释,总是说原子性是不可分割的。 那只是在单核心下的语义,单核心下不可分割的操作意味着执行过程中不会有其它线程执行,从而导致变量污染,也就是原子性操作涉及的共享变量是安全的。 所以多线程下原子性的语义也应该是 :原子性操作涉及的共享变量是安全的,不会有其它线程修改。 也就是说
阅读全文
摘要:总结: 1. 如果在单线程环境下,几个操作共享变量的方法存在数据依赖关系,那么多线程环境下它们必须是一组原子操作,且与任何修改共享变量的方法互斥。与读方法是否互斥需要看程序的设计,比如 CopyOnWrite 模式下,这些原子操作不会与读共享变量的动作互斥,可以提高读的效率,但缺点是不能保证读操作每
阅读全文
摘要:写过 JAVA 并发代码的同学对 synchronized 关键字一定是熟的不能再熟了,其基于对象头部的 monitor 实现了对代码块的加锁,使一段代码变为线程不可重入的。 synchronized 与操作系统层的 lock 与 unlock 机制非常类似,多线程通过一个共享变量通信,这个共享变量
阅读全文
摘要:happen-before 可真是一个经典又老生常谈的话题,规则一共就八条,但看起来总有种抓不住重点的感觉。今天再整理一下对这八条规则的理解。 首先我的理解是 happen-before 的语义与在什么什么之前发生完全没有关系,其语义是如果 A hapen-bfore B,那么 A 的结果对 B 是
阅读全文
摘要:数据一致性部分借用大神“耗叔”的博客:https://coolshell.cn/articles/20793.html。 总结:volatile 关键字通过内存屏障禁止了指令的重排序,并在单个核心中,强制数据的更新及时更新到缓存。在此基础上,依靠多核心处理器的缓存一致性协议等机制,保证了变量的可见性
阅读全文
摘要:CPU 在运行时为了响应外部的请求,对外提供了一个中断引脚。CPU 在每个指令周期的最后一个晶振周期检查中断引脚,如果有中断任务,则立即停止手中的工作(当然要先保存现场)调用相应中断号的中断处理程序对中断做出响应。 进程在运行时为了响应外部请求,对外提供了信号队列。在每次由核心态转为用户态(比如由进
阅读全文