ARTS第十三周(阅读Tomcat源码)
1.Algorithm:每周至少做一个 leetcode 的算法题
2.Review:阅读并点评至少一篇英文技术文章
3.Tip:学习至少一个技术技巧
4.Share:分享一篇有观点和思考的技术文章
考研真难 , 卷的厉害 , 还能怎么着 . 接着熬 , 继续更新
以下是各项的情况:
Algorithm
链接:[LeetCode-442]-Find All Duplicates in an Array
题意:
给定一个链表: 1->2->3->4->5, 和 n = 2. 当删除了倒数第二个节点后,链表变为 1->2->3->5.
分析:
以前做过一个类似题目 , 用hashmap 做一个对照词典 , 有重复的就返回
class Solution { public int findRepeatNumber(int[] nums) { HashSet dictionary = new HashSet<Integer>(); for (int num:nums){ if(dictionary.contains(num)){ return num; } dictionary.add(num); } return -1; } }
照着做就完事
class Solution { public List<Integer> findDuplicates(int[] nums) { List<Integer> res = new ArrayList<>(); if (nums == null || nums.length == 0) { return res; } // 一样的hash for (int i = 0; i < nums.length; i++) { while (nums[nums[i] - 1] != nums[i]) { swap(nums, i, nums[i] - 1); } } // 词典记录不重复 for (int i = 0; i < nums.length; i++) { if (nums[i] != i + 1) { res.add(nums[i]); } } return res; } public void swap(int[] arr, int index1, int index2) { int tmp = arr[index1]; arr[index1] = arr[index2]; arr[index2] = tmp; } }
Review
很多 归纳一下就是 :
始终严格的浮点语义、外部函数和内存 API 以及伪随机数生成器的统一 API
功能包括 :
特定于上下文的反序列化过滤器支持 (允许应用程序通过调用 JVM 范围的过滤器工厂来配置特定于上下文和动态选择的反序列化过滤器),这是一项安全增强 (反序列化过滤器被引入Java 9使应用程序和库代码能够在反序列化之前验证传入的数据流。此代码java.io.ObjectInputFilter
在创建反序列化流时提供验证逻辑。但是,依赖流的创建者来明确请求验证有局限性。JDK Enhancement Proposal 290通过引入可通过 API、系统属性或安全属性设置的 JVM 范围的反序列化过滤器解决了这些限制,但这种方法也有局限性,尤其是在复杂的应用程序中。更好的方法是配置每个流过滤器,这样它们就不需要每个流创建者的参与。always-strict 浮点语义的恢复,浮点运算将变得始终严格)
模式匹配 switch 语句 (switch
针对多个模式测试表达式和语句,每个模式都有特定的操作。 引入两种模式:guarded patterns
,允许模式匹配逻辑用任意布尔表达式和 parenthesized patterns . 在JDK 16 中,
)instanceof
运算符被扩展为采用类型模式并执行模式匹配。提议的适度扩展允许简化熟悉的 instanceof-and-cast 习语。
删除远程方法调用 (RMI) 激活机制 (同时保留 RMI 的其余部分。RMI 激活机制已过时和废弃,在JDK 15 中不推荐使用。)
增强的伪随机数生成器将为伪随机数生成器 (PRNG) 提供新的接口类型和实现,包括可跳转的 PRNG 和额外的一类可拆分 PRNG 算法 (LXM)。新接口RandomGenerator
将为所有现有的和新的 PRNG 提供统一的 API。将提供四个专门的 RandomGenerator 接口。推动该计划的重点是 Java 伪随机数生成领域的多个改进领域。 该计划的目标包括:
- 使在应用程序中交替使用各种 PRNG 算法变得更容易。
- 改进了对基于流的编程的支持,提供了 PRNG 对象流。
- 消除现有 PRNG 类中的代码重复。
-
保留类的现有行为
java.util.Random
。
还有些其他的 就不翻译了.
Tip
这几天朋友问了个问题: 请求一个网站很久超时,对应后台接口作用是导出大量数据的接口应用,请求导出一大批数据要执行很久,但是 http 等待到限制的时间后,链接就会断开并显示请求超时 , 而后台应用是一个子线程在处理 ,这时候这个子线程是随着链接断开而结束呢还是继续做完未完成任务 ? (我浏览器请求后台服务,后台执行很长时间,但是浏览器请求超时了,这时候,后台服务还没执行完,该子线程如何处理?继续还是?)
我很快回答了:看策略,设定的失败处理。同步就挂起等待 , 异步看你处理逻辑怎么写的。要写销毁就销毁 等待就挂起 。
很快朋友就追问:那默认的Tomcat策略是什么?
这难倒我了,平常业务都是自己写失败处理。不过,要让我们自己@override写失败处理,我猜默认的应该很辣鸡,Tomcat要是处理的好,就不会有rocketMQ用守护线程轮询对应线程强制结束了。所以首先我先大胆猜:继续执行,但是返回数据没对应的接受,所以一般自己处理都会轮询对应线程未响应直接销毁,然后等下次响应。
不过猜的不算数,我想看看原本的策略是什么? 于是首先发现很有意思的问题 现在用的 springboot,cloud 都是用 maven 或者 gradle ,都是集成了 Tomcat 的 。那么现在用的 maven 3.6 对应的 Tomcat 版本是多少 ?它的对应关系怎么样 ? http://tomcat.apache.org/whichversion.html 查询
再查询 http://maven.apache.org/docs/history.html
很有趣,得出结论 tomcat版本与maven版本没有直接的关系,tomcat是java写的一个web容器,maven是java写的一个项目,他们都需要Java环境运行 。 再继续我们的问题 ,对应的 Tomcat 处理策略是哪个包 ?
如果有看的读者 可以自己去尝试阅读阅读源码 , 提高能力 。 这里我不多BB直接给答案:
1. tomcat 8 消息处理 从org.apache.tomcat.util.net.JIoEndpoint$Acceptor#run 开始 , socket处理 就是记录在日志里
2. 然后再去getWorkerThread().assign(socket) 分了两部 先在线程池取一个线程启动 再去assign(socket)分配socket , 用了同步锁
3.再去IoEndpoint$Worker#run
抛异常才结束
果然我的猜测是正确的 。默认就是等待挂起睡1000ms,后台继续跑着 , 除非异常 比如后台跑时间太久 内存溢出 记到日志文件里 然后close soctet
Share
暂时没找到合适的 , 迟点再补 .