From 5a71060fe604922bb87d3715b0fd40be5505ef81 Mon Sep 17 00:00:00 2001 From: nicksxs Date: Sat, 2 Apr 2022 15:48:46 +0800 Subject: [PATCH] Site updated: 2022-04-02 15:48:44 --- .../04/聊聊-dubbo-的线程池/index.html | 2 +- leancloud.memo | 1 + leancloud_counter_security_urls.json | 2 +- page/12/index.html | 2 +- search.xml | 5124 ++++++++--------- sitemap.xml | 1364 ++--- 6 files changed, 3248 insertions(+), 3247 deletions(-) diff --git a/2021/04/04/聊聊-dubbo-的线程池/index.html b/2021/04/04/聊聊-dubbo-的线程池/index.html index 508b024ea7..1d8796d4f1 100644 --- a/2021/04/04/聊聊-dubbo-的线程池/index.html +++ b/2021/04/04/聊聊-dubbo-的线程池/index.html @@ -1,4 +1,4 @@ -聊聊 dubbo 的线程池 | Nicksxs's Blog

Nicksxs's Blog

What hurts more, the pain of hard work or the pain of regret?

0%

聊聊 dubbo 的线程池

之前没注意到这一块,只是比较模糊的印象 dubbo 自己基于 ThreadPoolExecutor 定义了几个线程池,但是没具体看过,主要是觉得就是为了避免使用 jdk 自带的那几个(java.util.concurrent.Executors),防止出现那些问题
看下代码目录主要是这几个

  • FixedThreadPool:创建一个复用固定个数线程的线程池。
    简单看下代码
    public Executor getExecutor(URL url) {
    +聊聊 dubbo 的线程池 | Nicksxs's Blog

    Nicksxs's Blog

    What hurts more, the pain of hard work or the pain of regret?

    0%

    聊聊 dubbo 的线程池

    之前没注意到这一块,只是比较模糊的印象 dubbo 自己基于 ThreadPoolExecutor 定义了几个线程池,但是没具体看过,主要是觉得就是为了避免使用 jdk 自带的那几个(java.util.concurrent.Executors),防止出现那些问题
    看下代码目录主要是这几个

    • FixedThreadPool:创建一个复用固定个数线程的线程池。
      简单看下代码
      public Executor getExecutor(URL url) {
               String name = url.getParameter("threadname", "Dubbo");
               int threads = url.getParameter("threads", 200);
               int queues = url.getParameter("queues", 0);
      diff --git a/leancloud.memo b/leancloud.memo
      index 9e44d69594..3f0eba9c3a 100644
      --- a/leancloud.memo
      +++ b/leancloud.memo
      @@ -153,4 +153,5 @@
       {"title":"Leetcode 349 两个数组的交集 ( Intersection of Two Arrays *Easy* ) 题解分析","url":"/2022/03/07/Leetcode-349-两个数组的交集-Intersection-of-Two-Arrays-Easy-题解分析/"},
       {"title":"Leetcode 83 删除排序链表中的重复元素 ( Remove Duplicates from Sorted List *Easy* ) 题解分析","url":"/2022/03/13/Leetcode-83-删除排序链表中的重复元素-Remove-Duplicates-from-Sorted-List-Easy-题解分析/"},
       {"title":"给小电驴上牌","url":"/2022/03/20/给小电驴上牌/"},
      +{"title":"Leetcode 4 寻找两个正序数组的中位数 ( Median of Two Sorted Arrays *Hard* ) 题解分析","url":"/2022/03/27/Leetcode-4-寻找两个正序数组的中位数-Median-of-Two-Sorted-Arrays-Hard-题解分析/"},
       ]
      \ No newline at end of file
      diff --git a/leancloud_counter_security_urls.json b/leancloud_counter_security_urls.json
      index 46fc80b9f1..eed780d77f 100644
      --- a/leancloud_counter_security_urls.json
      +++ b/leancloud_counter_security_urls.json
      @@ -1 +1 @@
      -[{"title":"村上春树《1Q84》读后感","url":"/2019/12/18/1Q84读后感/"},{"title":"2020 年终总结","url":"/2021/03/31/2020-年终总结/"},{"title":"2020年中总结","url":"/2020/07/11/2020年中总结/"},{"title":"2019年终总结","url":"/2020/02/01/2019年终总结/"},{"title":"34_Search_for_a_Range","url":"/2016/08/14/34-Search-for-a-Range/"},{"title":"2021 年中总结","url":"/2021/07/18/2021-年中总结/"},{"title":"AQS篇二 之 Condition 浅析笔记","url":"/2021/02/21/AQS-之-Condition-浅析笔记/"},{"title":"2021 年终总结","url":"/2022/01/22/2021-年终总结/"},{"title":"AQS篇一","url":"/2021/02/14/AQS篇一/"},{"title":"AbstractQueuedSynchronizer","url":"/2019/09/23/AbstractQueuedSynchronizer/"},{"title":"add-two-number","url":"/2015/04/14/Add-Two-Number/"},{"title":"Apollo 的 value 注解是怎么自动更新的","url":"/2020/11/01/Apollo-的-value-注解是怎么自动更新的/"},{"title":"Clone Graph Part I","url":"/2014/12/30/Clone-Graph-Part-I/"},{"title":"Comparator使用小记","url":"/2020/04/05/Comparator使用小记/"},{"title":"Filter, Interceptor, Aop, 啥, 啥, 啥? 这些都是啥?","url":"/2020/08/22/Filter-Intercepter-Aop-啥-啥-啥-这些都是啥/"},{"title":"G1收集器概述","url":"/2020/02/09/G1收集器概述/"},{"title":"Disruptor 系列二","url":"/2022/02/27/Disruptor-系列二/"},{"title":"Disruptor 系列一","url":"/2022/02/13/Disruptor-系列一/"},{"title":"Leetcode 021 合并两个有序链表 ( Merge Two Sorted Lists ) 题解分析","url":"/2021/10/07/Leetcode-021-合并两个有序链表-Merge-Two-Sorted-Lists-题解分析/"},{"title":"JVM源码分析之G1垃圾收集器分析一","url":"/2019/12/07/JVM-G1-Part-1/"},{"title":"Leetcode 028 实现 strStr() ( Implement strStr() ) 题解分析","url":"/2021/10/31/Leetcode-028-实现-strStr-Implement-strStr-题解分析/"},{"title":"Leetcode 053 最大子序和 ( Maximum Subarray ) 题解分析","url":"/2021/11/28/Leetcode-053-最大子序和-Maximum-Subarray-题解分析/"},{"title":"Leetcode 104 二叉树的最大深度(Maximum Depth of Binary Tree) 题解分析","url":"/2020/10/25/Leetcode-104-二叉树的最大深度-Maximum-Depth-of-Binary-Tree-题解分析/"},{"title":"Leetcode 105 从前序与中序遍历序列构造二叉树(Construct Binary Tree from Preorder and Inorder Traversal) 题解分析","url":"/2020/12/13/Leetcode-105-从前序与中序遍历序列构造二叉树-Construct-Binary-Tree-from-Preorder-and-Inorder-Traversal-题解分析/"},{"title":"Leetcode 121 买卖股票的最佳时机(Best Time to Buy and Sell Stock) 题解分析","url":"/2021/03/14/Leetcode-121-买卖股票的最佳时机-Best-Time-to-Buy-and-Sell-Stock-题解分析/"},{"title":"Leetcode 124 二叉树中的最大路径和(Binary Tree Maximum Path Sum) 题解分析","url":"/2021/01/24/Leetcode-124-二叉树中的最大路径和-Binary-Tree-Maximum-Path-Sum-题解分析/"},{"title":"Leetcode 155 最小栈(Min Stack) 题解分析","url":"/2020/12/06/Leetcode-155-最小栈-Min-Stack-题解分析/"},{"title":"Leetcode 160 相交链表(intersection-of-two-linked-lists) 题解分析","url":"/2021/01/10/Leetcode-160-相交链表-intersection-of-two-linked-lists-题解分析/"},{"title":"Leetcode 2 Add Two Numbers 题解分析","url":"/2020/10/11/Leetcode-2-Add-Two-Numbers-题解分析/"},{"title":"Leetcode 234 回文链表(Palindrome Linked List) 题解分析","url":"/2020/11/15/Leetcode-234-回文联表-Palindrome-Linked-List-题解分析/"},{"title":"Leetcode 236 二叉树的最近公共祖先(Lowest Common Ancestor of a Binary Tree) 题解分析","url":"/2021/05/23/Leetcode-236-二叉树的最近公共祖先-Lowest-Common-Ancestor-of-a-Binary-Tree-题解分析/"},{"title":"Leetcode 3 Longest Substring Without Repeating Characters 题解分析","url":"/2020/09/20/Leetcode-3-Longest-Substring-Without-Repeating-Characters-题解分析/"},{"title":"Leetcode 349 两个数组的交集 ( Intersection of Two Arrays *Easy* ) 题解分析","url":"/2022/03/07/Leetcode-349-两个数组的交集-Intersection-of-Two-Arrays-Easy-题解分析/"},{"title":"Leetcode 4 寻找两个正序数组的中位数 ( Median of Two Sorted Arrays *Hard* ) 题解分析","url":"/2022/03/27/Leetcode-4-寻找两个正序数组的中位数-Median-of-Two-Sorted-Arrays-Hard-题解分析/"},{"title":"Leetcode 42 接雨水 (Trapping Rain Water) 题解分析","url":"/2021/07/04/Leetcode-42-接雨水-Trapping-Rain-Water-题解分析/"},{"title":"Leetcode 48 旋转图像(Rotate Image) 题解分析","url":"/2021/05/01/Leetcode-48-旋转图像-Rotate-Image-题解分析/"},{"title":"Leetcode 83 删除排序链表中的重复元素 ( Remove Duplicates from Sorted List *Easy* ) 题解分析","url":"/2022/03/13/Leetcode-83-删除排序链表中的重复元素-Remove-Duplicates-from-Sorted-List-Easy-题解分析/"},{"title":"leetcode no.3","url":"/2015/04/15/Leetcode-No-3/"},{"title":"Linux 下 grep 命令的一点小技巧","url":"/2020/08/06/Linux-下-grep-命令的一点小技巧/"},{"title":"MFC 模态对话框","url":"/2014/12/24/MFC 模态对话框/"},{"title":"Maven实用小技巧","url":"/2020/02/16/Maven实用小技巧/"},{"title":"Number of 1 Bits","url":"/2015/03/11/Number-Of-1-Bits/"},{"title":"Path Sum","url":"/2015/01/04/Path-Sum/"},{"title":"Redis_分布式锁","url":"/2019/12/10/Redis-Part-1/"},{"title":"Reverse Bits","url":"/2015/03/11/Reverse-Bits/"},{"title":"Reverse Integer","url":"/2015/03/13/Reverse-Integer/"},{"title":"two sum","url":"/2015/01/14/Two-Sum/"},{"title":"ambari-summary","url":"/2017/05/09/ambari-summary/"},{"title":"binary-watch","url":"/2016/09/29/binary-watch/"},{"title":"docker-mysql-cluster","url":"/2016/08/14/docker-mysql-cluster/"},{"title":"docker比一般多一点的初学者介绍","url":"/2020/03/08/docker比一般多一点的初学者介绍/"},{"title":"docker比一般多一点的初学者介绍三","url":"/2020/03/21/docker比一般多一点的初学者介绍三/"},{"title":"docker比一般多一点的初学者介绍二","url":"/2020/03/15/docker比一般多一点的初学者介绍二/"},{"title":"docker使用中发现的echo命令的一个小技巧及其他","url":"/2020/03/29/echo命令的一个小技巧/"},{"title":"gogs使用webhook部署react单页应用","url":"/2020/02/22/gogs使用webhook部署react单页应用/"},{"title":"invert-binary-tree","url":"/2015/06/22/invert-binary-tree/"},{"title":"minimum-size-subarray-sum-209","url":"/2016/10/11/minimum-size-subarray-sum-209/"},{"title":"C++ 指针使用中的一个小问题","url":"/2014/12/23/my-new-post/"},{"title":"mybatis 的 $ 和 # 是有啥区别","url":"/2020/09/06/mybatis-的-和-是有啥区别/"},{"title":"mybatis 的缓存是怎么回事","url":"/2020/10/03/mybatis-的缓存是怎么回事/"},{"title":"openresty","url":"/2019/06/18/openresty/"},{"title":"pcre-intro-and-a-simple-package","url":"/2015/01/16/pcre-intro-and-a-simple-package/"},{"title":"php-abstract-class-and-interface","url":"/2016/11/10/php-abstract-class-and-interface/"},{"title":"rabbitmq-tips","url":"/2017/04/25/rabbitmq-tips/"},{"title":"redis 的 rdb 和 COW 介绍","url":"/2021/08/15/redis-的-rdb-和-COW-介绍/"},{"title":"redis数据结构介绍-第一部分 SDS,链表,字典","url":"/2019/12/26/redis数据结构介绍/"},{"title":"redis数据结构介绍三-第三部分 整数集合","url":"/2020/01/10/redis数据结构介绍三/"},{"title":"redis数据结构介绍二-第二部分 跳表","url":"/2020/01/04/redis数据结构介绍二/"},{"title":"redis数据结构介绍五-第五部分 对象","url":"/2020/01/20/redis数据结构介绍五/"},{"title":"redis数据结构介绍六 快表","url":"/2020/01/22/redis数据结构介绍六/"},{"title":"redis数据结构介绍四-第四部分 压缩表","url":"/2020/01/19/redis数据结构介绍四/"},{"title":"redis淘汰策略复习","url":"/2021/08/01/redis淘汰策略复习/"},{"title":"redis系列介绍七-过期策略","url":"/2020/04/12/redis系列介绍七/"},{"title":"redis系列介绍八-淘汰策略","url":"/2020/04/18/redis系列介绍八/"},{"title":"redis过期策略复习","url":"/2021/07/25/redis过期策略复习/"},{"title":"rust学习笔记-所有权三之切片","url":"/2021/05/16/rust学习笔记-所有权三之切片/"},{"title":"rust学习笔记-所有权二","url":"/2021/04/18/rust学习笔记-所有权二/"},{"title":"rust学习笔记-所有权一","url":"/2021/04/18/rust学习笔记/"},{"title":"spark-little-tips","url":"/2017/03/28/spark-little-tips/"},{"title":"spring event 介绍","url":"/2022/01/30/spring-event-介绍/"},{"title":"summary-ranges-228","url":"/2016/10/12/summary-ranges-228/"},{"title":"swoole-websocket-test","url":"/2016/07/13/swoole-websocket-test/"},{"title":"wordpress 忘记密码的一种解决方法","url":"/2021/12/05/wordpress-忘记密码的一种解决方法/"},{"title":"《垃圾回收算法手册读书》笔记之整理算法","url":"/2021/03/07/《垃圾回收算法手册读书》笔记之整理算法/"},{"title":"介绍一下 RocketMQ","url":"/2020/06/21/介绍一下-RocketMQ/"},{"title":"介绍下最近比较实用的端口转发","url":"/2021/11/14/介绍下最近比较实用的端口转发/"},{"title":"从丁仲礼被美国制裁聊点啥","url":"/2020/12/20/从丁仲礼被美国制裁聊点啥/"},{"title":"从清华美院学姐聊聊我们身边的恶人","url":"/2020/11/29/从清华美院学姐聊聊我们身边的恶人/"},{"title":"关于公共交通再吐个槽","url":"/2021/03/21/关于公共交通再吐个槽/"},{"title":"关于读书打卡与分享","url":"/2021/02/07/关于读书打卡与分享/"},{"title":"周末我在老丈人家打了天小工","url":"/2020/08/16/周末我在老丈人家打了天小工/"},{"title":"在老丈人家的小工记三","url":"/2020/09/13/在老丈人家的小工记三/"},{"title":"在老丈人家的小工记五","url":"/2020/10/18/在老丈人家的小工记五/"},{"title":"在老丈人家的小工记四","url":"/2020/09/26/在老丈人家的小工记四/"},{"title":"寄生虫观后感","url":"/2020/03/01/寄生虫观后感/"},{"title":"我是如何走上跑步这条不归路的","url":"/2020/07/26/我是如何走上跑步这条不归路的/"},{"title":"分享记录一下一个 git 操作方法","url":"/2022/02/06/分享记录一下一个-git-操作方法/"},{"title":"上次的其他 外行聊国足","url":"/2022/03/06/上次的其他-外行聊国足/"},{"title":"看完了扫黑风暴,聊聊感想","url":"/2021/10/24/看完了扫黑风暴-聊聊感想/"},{"title":"聊一下 RocketMQ 的 DefaultMQPushConsumer 源码","url":"/2020/06/26/聊一下-RocketMQ-的-Consumer/"},{"title":"聊一下 RocketMQ 的 NameServer 源码","url":"/2020/07/05/聊一下-RocketMQ-的-NameServer-源码/"},{"title":"聊一下 RocketMQ 的消息存储之 MMAP","url":"/2021/09/04/聊一下-RocketMQ-的消息存储/"},{"title":"聊一下 RocketMQ 的消息存储三","url":"/2021/10/03/聊一下-RocketMQ-的消息存储三/"},{"title":"分享记录一下一个 scp 操作方法","url":"/2022/02/06/分享记录一下一个-scp-操作方法/"},{"title":"聊一下 RocketMQ 的消息存储二","url":"/2021/09/12/聊一下-RocketMQ-的消息存储二/"},{"title":"聊一下 RocketMQ 的消息存储四","url":"/2021/10/17/聊一下-RocketMQ-的消息存储四/"},{"title":"聊一下 RocketMQ 的顺序消息","url":"/2021/08/29/聊一下-RocketMQ-的顺序消息/"},{"title":"聊一下 SpringBoot 中使用的 cglib 作为动态代理中的一个注意点","url":"/2021/09/19/聊一下-SpringBoot-中使用的-cglib-作为动态代理中的一个注意点/"},{"title":"聊一下 SpringBoot 中动态切换数据源的方法","url":"/2021/09/26/聊一下-SpringBoot-中动态切换数据源的方法/"},{"title":"聊在东京奥运会闭幕式这天-二","url":"/2021/08/19/聊在东京奥运会闭幕式这天-二/"},{"title":"聊在东京奥运会闭幕式这天","url":"/2021/08/08/聊在东京奥运会闭幕式这天/"},{"title":"聊聊 Dubbo 的 SPI 续之自适应拓展","url":"/2020/06/06/聊聊-Dubbo-的-SPI-续之自适应拓展/"},{"title":"聊聊 Dubbo 的 SPI","url":"/2020/05/31/聊聊-Dubbo-的-SPI/"},{"title":"聊聊 Dubbo 的容错机制","url":"/2020/11/22/聊聊-Dubbo-的容错机制/"},{"title":"搬运两个 StackOverflow 上的 Mysql 编码相关的问题解答","url":"/2022/01/16/搬运两个-StackOverflow-上的-Mysql-编码相关的问题解答/"},{"title":"给小电驴上牌","url":"/2022/03/20/给小电驴上牌/"},{"title":"聊聊 Java 中绕不开的 Synchronized 关键字-二","url":"/2021/06/27/聊聊-Java-中绕不开的-Synchronized-关键字-二/"},{"title":"聊聊 Java 的 equals 和 hashCode 方法","url":"/2021/01/03/聊聊-Java-的-equals-和-hashCode-方法/"},{"title":"聊聊 Java 中绕不开的 Synchronized 关键字","url":"/2021/06/20/聊聊-Java-中绕不开的-Synchronized-关键字/"},{"title":"聊聊 Java 的类加载机制一","url":"/2020/11/08/聊聊-Java-的类加载机制/"},{"title":"聊聊 Java 的类加载机制二","url":"/2021/06/13/聊聊-Java-的类加载机制二/"},{"title":"聊聊 Java 自带的那些*逆天*工具","url":"/2020/08/02/聊聊-Java-自带的那些逆天工具/"},{"title":"聊聊 Linux 下的 top 命令","url":"/2021/03/28/聊聊-Linux-下的-top-命令/"},{"title":"聊聊 RocketMQ 的 Broker 源码","url":"/2020/07/19/聊聊-RocketMQ-的-Broker-源码/"},{"title":"聊聊 Sharding-Jdbc 的简单使用","url":"/2021/12/12/聊聊-Sharding-Jdbc-的简单使用/"},{"title":"聊聊 Sharding-Jdbc 的简单原理初篇","url":"/2021/12/26/聊聊-Sharding-Jdbc-的简单原理初篇/"},{"title":"聊聊 dubbo 的线程池","url":"/2021/04/04/聊聊-dubbo-的线程池/"},{"title":"聊聊 mysql 的 MVCC 续篇","url":"/2020/05/02/聊聊-mysql-的-MVCC-续篇/"},{"title":"聊聊 mysql 的 MVCC 续续篇之锁分析","url":"/2020/05/10/聊聊-mysql-的-MVCC-续续篇之加锁分析/"},{"title":"聊聊 redis 缓存的应用问题","url":"/2021/01/31/聊聊-redis-缓存的应用问题/"},{"title":"聊聊 mysql 的 MVCC","url":"/2020/04/26/聊聊-mysql-的-MVCC/"},{"title":"聊聊 mysql 索引的一些细节","url":"/2020/12/27/聊聊-mysql-索引的一些细节/"},{"title":"聊聊Java中的单例模式","url":"/2019/12/21/聊聊Java中的单例模式/"},{"title":"聊聊 SpringBoot 自动装配","url":"/2021/07/11/聊聊SpringBoot-自动装配/"},{"title":"聊聊传说中的 ThreadLocal","url":"/2021/05/30/聊聊传说中的-ThreadLocal/"},{"title":"聊聊一次 brew update 引发的血案","url":"/2020/06/13/聊聊一次-brew-update-引发的血案/"},{"title":"聊聊厦门旅游的好与不好","url":"/2021/04/11/聊聊厦门旅游的好与不好/"},{"title":"聊聊如何识别和意识到日常生活中的各类危险","url":"/2021/06/06/聊聊如何识别和意识到日常生活中的各类危险/"},{"title":"聊聊我理解的分布式事务","url":"/2020/05/17/聊聊我理解的分布式事务/"},{"title":"聊聊我刚学会的应用诊断方法","url":"/2020/05/22/聊聊我刚学会的应用诊断方法/"},{"title":"聊聊最近平淡的生活之又聊通勤","url":"/2021/11/07/聊聊最近平淡的生活/"},{"title":"聊聊 Sharding-Jdbc 分库分表下的分页方案","url":"/2022/01/09/聊聊-Sharding-Jdbc-分库分表下的分页方案/"},{"title":"聊聊最近平淡的生活之看《神探狄仁杰》","url":"/2021/12/19/聊聊最近平淡的生活之看《神探狄仁杰》/"},{"title":"聊聊最近平淡的生活之看看老剧","url":"/2021/11/21/聊聊最近平淡的生活之看看老剧/"},{"title":"聊聊给亲戚朋友的老电脑重装系统那些事儿","url":"/2021/05/09/聊聊给亲戚朋友的老电脑重装系统那些事儿/"},{"title":"聊聊那些加塞狗","url":"/2021/01/17/聊聊那些加塞狗/"},{"title":"聊聊部分公交车的设计bug","url":"/2021/12/05/聊聊部分公交车的设计bug/"},{"title":"这周末我又在老丈人家打了天小工","url":"/2020/08/30/这周末我又在老丈人家打了天小工/"},{"title":"重看了下《蛮荒记》说说感受","url":"/2021/10/10/重看了下《蛮荒记》说说感受/"},{"title":"闲聊下乘公交的用户体验","url":"/2021/02/28/闲聊下乘公交的用户体验/"},{"title":"聊聊最近平淡的生活之《花束般的恋爱》观后感","url":"/2021/12/31/聊聊最近平淡的生活之《花束般的恋爱》观后感/"},{"title":"聊聊这次换车牌及其他","url":"/2022/02/20/聊聊这次换车牌及其他/"}]
      \ No newline at end of file
      +[{"title":"村上春树《1Q84》读后感","url":"/2019/12/18/1Q84读后感/"},{"title":"2019年终总结","url":"/2020/02/01/2019年终总结/"},{"title":"2020 年终总结","url":"/2021/03/31/2020-年终总结/"},{"title":"2020年中总结","url":"/2020/07/11/2020年中总结/"},{"title":"34_Search_for_a_Range","url":"/2016/08/14/34-Search-for-a-Range/"},{"title":"AQS篇二 之 Condition 浅析笔记","url":"/2021/02/21/AQS-之-Condition-浅析笔记/"},{"title":"2021 年中总结","url":"/2021/07/18/2021-年中总结/"},{"title":"AbstractQueuedSynchronizer","url":"/2019/09/23/AbstractQueuedSynchronizer/"},{"title":"add-two-number","url":"/2015/04/14/Add-Two-Number/"},{"title":"AQS篇一","url":"/2021/02/14/AQS篇一/"},{"title":"2021 年终总结","url":"/2022/01/22/2021-年终总结/"},{"title":"Clone Graph Part I","url":"/2014/12/30/Clone-Graph-Part-I/"},{"title":"Apollo 的 value 注解是怎么自动更新的","url":"/2020/11/01/Apollo-的-value-注解是怎么自动更新的/"},{"title":"Comparator使用小记","url":"/2020/04/05/Comparator使用小记/"},{"title":"Disruptor 系列一","url":"/2022/02/13/Disruptor-系列一/"},{"title":"Disruptor 系列二","url":"/2022/02/27/Disruptor-系列二/"},{"title":"Filter, Interceptor, Aop, 啥, 啥, 啥? 这些都是啥?","url":"/2020/08/22/Filter-Intercepter-Aop-啥-啥-啥-这些都是啥/"},{"title":"G1收集器概述","url":"/2020/02/09/G1收集器概述/"},{"title":"JVM源码分析之G1垃圾收集器分析一","url":"/2019/12/07/JVM-G1-Part-1/"},{"title":"Leetcode 021 合并两个有序链表 ( Merge Two Sorted Lists ) 题解分析","url":"/2021/10/07/Leetcode-021-合并两个有序链表-Merge-Two-Sorted-Lists-题解分析/"},{"title":"Leetcode 028 实现 strStr() ( Implement strStr() ) 题解分析","url":"/2021/10/31/Leetcode-028-实现-strStr-Implement-strStr-题解分析/"},{"title":"Leetcode 053 最大子序和 ( Maximum Subarray ) 题解分析","url":"/2021/11/28/Leetcode-053-最大子序和-Maximum-Subarray-题解分析/"},{"title":"Leetcode 104 二叉树的最大深度(Maximum Depth of Binary Tree) 题解分析","url":"/2020/10/25/Leetcode-104-二叉树的最大深度-Maximum-Depth-of-Binary-Tree-题解分析/"},{"title":"Leetcode 105 从前序与中序遍历序列构造二叉树(Construct Binary Tree from Preorder and Inorder Traversal) 题解分析","url":"/2020/12/13/Leetcode-105-从前序与中序遍历序列构造二叉树-Construct-Binary-Tree-from-Preorder-and-Inorder-Traversal-题解分析/"},{"title":"Leetcode 121 买卖股票的最佳时机(Best Time to Buy and Sell Stock) 题解分析","url":"/2021/03/14/Leetcode-121-买卖股票的最佳时机-Best-Time-to-Buy-and-Sell-Stock-题解分析/"},{"title":"Leetcode 124 二叉树中的最大路径和(Binary Tree Maximum Path Sum) 题解分析","url":"/2021/01/24/Leetcode-124-二叉树中的最大路径和-Binary-Tree-Maximum-Path-Sum-题解分析/"},{"title":"Leetcode 155 最小栈(Min Stack) 题解分析","url":"/2020/12/06/Leetcode-155-最小栈-Min-Stack-题解分析/"},{"title":"Leetcode 160 相交链表(intersection-of-two-linked-lists) 题解分析","url":"/2021/01/10/Leetcode-160-相交链表-intersection-of-two-linked-lists-题解分析/"},{"title":"Leetcode 2 Add Two Numbers 题解分析","url":"/2020/10/11/Leetcode-2-Add-Two-Numbers-题解分析/"},{"title":"Leetcode 234 回文链表(Palindrome Linked List) 题解分析","url":"/2020/11/15/Leetcode-234-回文联表-Palindrome-Linked-List-题解分析/"},{"title":"Leetcode 236 二叉树的最近公共祖先(Lowest Common Ancestor of a Binary Tree) 题解分析","url":"/2021/05/23/Leetcode-236-二叉树的最近公共祖先-Lowest-Common-Ancestor-of-a-Binary-Tree-题解分析/"},{"title":"Leetcode 3 Longest Substring Without Repeating Characters 题解分析","url":"/2020/09/20/Leetcode-3-Longest-Substring-Without-Repeating-Characters-题解分析/"},{"title":"Leetcode 4 寻找两个正序数组的中位数 ( Median of Two Sorted Arrays *Hard* ) 题解分析","url":"/2022/03/27/Leetcode-4-寻找两个正序数组的中位数-Median-of-Two-Sorted-Arrays-Hard-题解分析/"},{"title":"Leetcode 42 接雨水 (Trapping Rain Water) 题解分析","url":"/2021/07/04/Leetcode-42-接雨水-Trapping-Rain-Water-题解分析/"},{"title":"Leetcode 48 旋转图像(Rotate Image) 题解分析","url":"/2021/05/01/Leetcode-48-旋转图像-Rotate-Image-题解分析/"},{"title":"Leetcode 349 两个数组的交集 ( Intersection of Two Arrays *Easy* ) 题解分析","url":"/2022/03/07/Leetcode-349-两个数组的交集-Intersection-of-Two-Arrays-Easy-题解分析/"},{"title":"Leetcode 83 删除排序链表中的重复元素 ( Remove Duplicates from Sorted List *Easy* ) 题解分析","url":"/2022/03/13/Leetcode-83-删除排序链表中的重复元素-Remove-Duplicates-from-Sorted-List-Easy-题解分析/"},{"title":"leetcode no.3","url":"/2015/04/15/Leetcode-No-3/"},{"title":"Linux 下 grep 命令的一点小技巧","url":"/2020/08/06/Linux-下-grep-命令的一点小技巧/"},{"title":"MFC 模态对话框","url":"/2014/12/24/MFC 模态对话框/"},{"title":"Maven实用小技巧","url":"/2020/02/16/Maven实用小技巧/"},{"title":"Number of 1 Bits","url":"/2015/03/11/Number-Of-1-Bits/"},{"title":"Path Sum","url":"/2015/01/04/Path-Sum/"},{"title":"Redis_分布式锁","url":"/2019/12/10/Redis-Part-1/"},{"title":"Reverse Bits","url":"/2015/03/11/Reverse-Bits/"},{"title":"Reverse Integer","url":"/2015/03/13/Reverse-Integer/"},{"title":"two sum","url":"/2015/01/14/Two-Sum/"},{"title":"ambari-summary","url":"/2017/05/09/ambari-summary/"},{"title":"binary-watch","url":"/2016/09/29/binary-watch/"},{"title":"docker-mysql-cluster","url":"/2016/08/14/docker-mysql-cluster/"},{"title":"docker比一般多一点的初学者介绍","url":"/2020/03/08/docker比一般多一点的初学者介绍/"},{"title":"docker比一般多一点的初学者介绍三","url":"/2020/03/21/docker比一般多一点的初学者介绍三/"},{"title":"docker比一般多一点的初学者介绍二","url":"/2020/03/15/docker比一般多一点的初学者介绍二/"},{"title":"docker使用中发现的echo命令的一个小技巧及其他","url":"/2020/03/29/echo命令的一个小技巧/"},{"title":"gogs使用webhook部署react单页应用","url":"/2020/02/22/gogs使用webhook部署react单页应用/"},{"title":"invert-binary-tree","url":"/2015/06/22/invert-binary-tree/"},{"title":"minimum-size-subarray-sum-209","url":"/2016/10/11/minimum-size-subarray-sum-209/"},{"title":"mybatis 的 $ 和 # 是有啥区别","url":"/2020/09/06/mybatis-的-和-是有啥区别/"},{"title":"C++ 指针使用中的一个小问题","url":"/2014/12/23/my-new-post/"},{"title":"mybatis 的缓存是怎么回事","url":"/2020/10/03/mybatis-的缓存是怎么回事/"},{"title":"openresty","url":"/2019/06/18/openresty/"},{"title":"pcre-intro-and-a-simple-package","url":"/2015/01/16/pcre-intro-and-a-simple-package/"},{"title":"php-abstract-class-and-interface","url":"/2016/11/10/php-abstract-class-and-interface/"},{"title":"rabbitmq-tips","url":"/2017/04/25/rabbitmq-tips/"},{"title":"redis 的 rdb 和 COW 介绍","url":"/2021/08/15/redis-的-rdb-和-COW-介绍/"},{"title":"redis数据结构介绍-第一部分 SDS,链表,字典","url":"/2019/12/26/redis数据结构介绍/"},{"title":"redis数据结构介绍三-第三部分 整数集合","url":"/2020/01/10/redis数据结构介绍三/"},{"title":"redis数据结构介绍二-第二部分 跳表","url":"/2020/01/04/redis数据结构介绍二/"},{"title":"redis数据结构介绍五-第五部分 对象","url":"/2020/01/20/redis数据结构介绍五/"},{"title":"redis数据结构介绍六 快表","url":"/2020/01/22/redis数据结构介绍六/"},{"title":"redis数据结构介绍四-第四部分 压缩表","url":"/2020/01/19/redis数据结构介绍四/"},{"title":"redis淘汰策略复习","url":"/2021/08/01/redis淘汰策略复习/"},{"title":"redis系列介绍七-过期策略","url":"/2020/04/12/redis系列介绍七/"},{"title":"redis系列介绍八-淘汰策略","url":"/2020/04/18/redis系列介绍八/"},{"title":"redis过期策略复习","url":"/2021/07/25/redis过期策略复习/"},{"title":"rust学习笔记-所有权三之切片","url":"/2021/05/16/rust学习笔记-所有权三之切片/"},{"title":"rust学习笔记-所有权二","url":"/2021/04/18/rust学习笔记-所有权二/"},{"title":"spark-little-tips","url":"/2017/03/28/spark-little-tips/"},{"title":"rust学习笔记-所有权一","url":"/2021/04/18/rust学习笔记/"},{"title":"spring event 介绍","url":"/2022/01/30/spring-event-介绍/"},{"title":"summary-ranges-228","url":"/2016/10/12/summary-ranges-228/"},{"title":"wordpress 忘记密码的一种解决方法","url":"/2021/12/05/wordpress-忘记密码的一种解决方法/"},{"title":"swoole-websocket-test","url":"/2016/07/13/swoole-websocket-test/"},{"title":"《垃圾回收算法手册读书》笔记之整理算法","url":"/2021/03/07/《垃圾回收算法手册读书》笔记之整理算法/"},{"title":"上次的其他 外行聊国足","url":"/2022/03/06/上次的其他-外行聊国足/"},{"title":"介绍一下 RocketMQ","url":"/2020/06/21/介绍一下-RocketMQ/"},{"title":"介绍下最近比较实用的端口转发","url":"/2021/11/14/介绍下最近比较实用的端口转发/"},{"title":"从丁仲礼被美国制裁聊点啥","url":"/2020/12/20/从丁仲礼被美国制裁聊点啥/"},{"title":"从清华美院学姐聊聊我们身边的恶人","url":"/2020/11/29/从清华美院学姐聊聊我们身边的恶人/"},{"title":"关于读书打卡与分享","url":"/2021/02/07/关于读书打卡与分享/"},{"title":"关于公共交通再吐个槽","url":"/2021/03/21/关于公共交通再吐个槽/"},{"title":"周末我在老丈人家打了天小工","url":"/2020/08/16/周末我在老丈人家打了天小工/"},{"title":"分享记录一下一个 scp 操作方法","url":"/2022/02/06/分享记录一下一个-scp-操作方法/"},{"title":"分享记录一下一个 git 操作方法","url":"/2022/02/06/分享记录一下一个-git-操作方法/"},{"title":"在老丈人家的小工记三","url":"/2020/09/13/在老丈人家的小工记三/"},{"title":"在老丈人家的小工记五","url":"/2020/10/18/在老丈人家的小工记五/"},{"title":"在老丈人家的小工记四","url":"/2020/09/26/在老丈人家的小工记四/"},{"title":"寄生虫观后感","url":"/2020/03/01/寄生虫观后感/"},{"title":"我是如何走上跑步这条不归路的","url":"/2020/07/26/我是如何走上跑步这条不归路的/"},{"title":"看完了扫黑风暴,聊聊感想","url":"/2021/10/24/看完了扫黑风暴-聊聊感想/"},{"title":"搬运两个 StackOverflow 上的 Mysql 编码相关的问题解答","url":"/2022/01/16/搬运两个-StackOverflow-上的-Mysql-编码相关的问题解答/"},{"title":"聊一下 RocketMQ 的 DefaultMQPushConsumer 源码","url":"/2020/06/26/聊一下-RocketMQ-的-Consumer/"},{"title":"聊一下 RocketMQ 的 NameServer 源码","url":"/2020/07/05/聊一下-RocketMQ-的-NameServer-源码/"},{"title":"聊一下 RocketMQ 的消息存储之 MMAP","url":"/2021/09/04/聊一下-RocketMQ-的消息存储/"},{"title":"给小电驴上牌","url":"/2022/03/20/给小电驴上牌/"},{"title":"聊一下 RocketMQ 的消息存储三","url":"/2021/10/03/聊一下-RocketMQ-的消息存储三/"},{"title":"聊一下 RocketMQ 的消息存储二","url":"/2021/09/12/聊一下-RocketMQ-的消息存储二/"},{"title":"聊一下 RocketMQ 的消息存储四","url":"/2021/10/17/聊一下-RocketMQ-的消息存储四/"},{"title":"聊一下 RocketMQ 的顺序消息","url":"/2021/08/29/聊一下-RocketMQ-的顺序消息/"},{"title":"聊一下 SpringBoot 中使用的 cglib 作为动态代理中的一个注意点","url":"/2021/09/19/聊一下-SpringBoot-中使用的-cglib-作为动态代理中的一个注意点/"},{"title":"聊一下 SpringBoot 中动态切换数据源的方法","url":"/2021/09/26/聊一下-SpringBoot-中动态切换数据源的方法/"},{"title":"聊在东京奥运会闭幕式这天","url":"/2021/08/08/聊在东京奥运会闭幕式这天/"},{"title":"聊在东京奥运会闭幕式这天-二","url":"/2021/08/19/聊在东京奥运会闭幕式这天-二/"},{"title":"聊聊 Dubbo 的 SPI 续之自适应拓展","url":"/2020/06/06/聊聊-Dubbo-的-SPI-续之自适应拓展/"},{"title":"聊聊 Dubbo 的 SPI","url":"/2020/05/31/聊聊-Dubbo-的-SPI/"},{"title":"聊聊 Dubbo 的容错机制","url":"/2020/11/22/聊聊-Dubbo-的容错机制/"},{"title":"聊聊 Java 中绕不开的 Synchronized 关键字-二","url":"/2021/06/27/聊聊-Java-中绕不开的-Synchronized-关键字-二/"},{"title":"聊聊 Java 的 equals 和 hashCode 方法","url":"/2021/01/03/聊聊-Java-的-equals-和-hashCode-方法/"},{"title":"聊聊 Java 的类加载机制一","url":"/2020/11/08/聊聊-Java-的类加载机制/"},{"title":"聊聊 Java 的类加载机制二","url":"/2021/06/13/聊聊-Java-的类加载机制二/"},{"title":"聊聊 Java 中绕不开的 Synchronized 关键字","url":"/2021/06/20/聊聊-Java-中绕不开的-Synchronized-关键字/"},{"title":"聊聊 Linux 下的 top 命令","url":"/2021/03/28/聊聊-Linux-下的-top-命令/"},{"title":"聊聊 RocketMQ 的 Broker 源码","url":"/2020/07/19/聊聊-RocketMQ-的-Broker-源码/"},{"title":"聊聊 Java 自带的那些*逆天*工具","url":"/2020/08/02/聊聊-Java-自带的那些逆天工具/"},{"title":"聊聊 Sharding-Jdbc 的简单使用","url":"/2021/12/12/聊聊-Sharding-Jdbc-的简单使用/"},{"title":"聊聊 dubbo 的线程池","url":"/2021/04/04/聊聊-dubbo-的线程池/"},{"title":"聊聊 mysql 的 MVCC 续篇","url":"/2020/05/02/聊聊-mysql-的-MVCC-续篇/"},{"title":"聊聊 mysql 的 MVCC 续续篇之锁分析","url":"/2020/05/10/聊聊-mysql-的-MVCC-续续篇之加锁分析/"},{"title":"聊聊 Sharding-Jdbc 的简单原理初篇","url":"/2021/12/26/聊聊-Sharding-Jdbc-的简单原理初篇/"},{"title":"聊聊 mysql 的 MVCC","url":"/2020/04/26/聊聊-mysql-的-MVCC/"},{"title":"聊聊 Sharding-Jdbc 分库分表下的分页方案","url":"/2022/01/09/聊聊-Sharding-Jdbc-分库分表下的分页方案/"},{"title":"聊聊 mysql 索引的一些细节","url":"/2020/12/27/聊聊-mysql-索引的一些细节/"},{"title":"聊聊 redis 缓存的应用问题","url":"/2021/01/31/聊聊-redis-缓存的应用问题/"},{"title":"聊聊 SpringBoot 自动装配","url":"/2021/07/11/聊聊SpringBoot-自动装配/"},{"title":"聊聊一次 brew update 引发的血案","url":"/2020/06/13/聊聊一次-brew-update-引发的血案/"},{"title":"聊聊厦门旅游的好与不好","url":"/2021/04/11/聊聊厦门旅游的好与不好/"},{"title":"聊聊传说中的 ThreadLocal","url":"/2021/05/30/聊聊传说中的-ThreadLocal/"},{"title":"聊聊如何识别和意识到日常生活中的各类危险","url":"/2021/06/06/聊聊如何识别和意识到日常生活中的各类危险/"},{"title":"聊聊我刚学会的应用诊断方法","url":"/2020/05/22/聊聊我刚学会的应用诊断方法/"},{"title":"聊聊我理解的分布式事务","url":"/2020/05/17/聊聊我理解的分布式事务/"},{"title":"聊聊最近平淡的生活之又聊通勤","url":"/2021/11/07/聊聊最近平淡的生活/"},{"title":"聊聊最近平淡的生活之看《神探狄仁杰》","url":"/2021/12/19/聊聊最近平淡的生活之看《神探狄仁杰》/"},{"title":"聊聊最近平淡的生活之《花束般的恋爱》观后感","url":"/2021/12/31/聊聊最近平淡的生活之《花束般的恋爱》观后感/"},{"title":"聊聊最近平淡的生活之看看老剧","url":"/2021/11/21/聊聊最近平淡的生活之看看老剧/"},{"title":"聊聊给亲戚朋友的老电脑重装系统那些事儿","url":"/2021/05/09/聊聊给亲戚朋友的老电脑重装系统那些事儿/"},{"title":"聊聊这次换车牌及其他","url":"/2022/02/20/聊聊这次换车牌及其他/"},{"title":"聊聊那些加塞狗","url":"/2021/01/17/聊聊那些加塞狗/"},{"title":"聊聊部分公交车的设计bug","url":"/2021/12/05/聊聊部分公交车的设计bug/"},{"title":"这周末我又在老丈人家打了天小工","url":"/2020/08/30/这周末我又在老丈人家打了天小工/"},{"title":"重看了下《蛮荒记》说说感受","url":"/2021/10/10/重看了下《蛮荒记》说说感受/"},{"title":"闲聊下乘公交的用户体验","url":"/2021/02/28/闲聊下乘公交的用户体验/"},{"title":"聊聊Java中的单例模式","url":"/2019/12/21/聊聊Java中的单例模式/"}]
      \ No newline at end of file
      diff --git a/page/12/index.html b/page/12/index.html
      index c2b7bc9b69..3c6e80bd1f 100644
      --- a/page/12/index.html
      +++ b/page/12/index.html
      @@ -1,4 +1,4 @@
      -Nicksxs's Blog

      Nicksxs's Blog

      What hurts more, the pain of hard work or the pain of regret?

      0%

      之前没注意到这一块,只是比较模糊的印象 dubbo 自己基于 ThreadPoolExecutor 定义了几个线程池,但是没具体看过,主要是觉得就是为了避免使用 jdk 自带的那几个(java.util.concurrent.Executors),防止出现那些问题
      看下代码目录主要是这几个

      • FixedThreadPool:创建一个复用固定个数线程的线程池。
        简单看下代码
        public Executor getExecutor(URL url) {
        +Nicksxs's Blog

        Nicksxs's Blog

        What hurts more, the pain of hard work or the pain of regret?

        0%

        之前没注意到这一块,只是比较模糊的印象 dubbo 自己基于 ThreadPoolExecutor 定义了几个线程池,但是没具体看过,主要是觉得就是为了避免使用 jdk 自带的那几个(java.util.concurrent.Executors),防止出现那些问题
        看下代码目录主要是这几个

        • FixedThreadPool:创建一个复用固定个数线程的线程池。
          简单看下代码
          public Executor getExecutor(URL url) {
                   String name = url.getParameter("threadname", "Dubbo");
                   int threads = url.getParameter("threads", 200);
                   int queues = url.getParameter("queues", 0);
          diff --git a/search.xml b/search.xml
          index ec048d9a1f..d5ca648f3e 100644
          --- a/search.xml
          +++ b/search.xml
          @@ -20,6 +20,35 @@
                   读后感
                 
             
          +  
          +    2019年终总结
          +    /2020/02/01/2019%E5%B9%B4%E7%BB%88%E6%80%BB%E7%BB%93/
          +    今天是农历初八了,年前一个月的时候就准备做下今年的年终总结,可是写了一点觉得太情绪化了,希望后面写个平淡点的,正好最近技术方面还没有看到一个完整成文的内容,就来写一下这一年的总结,尽量少写一点太情绪化的东西。

          +

          跳槽

          年初换了个公司,也算换了个环境,跟前公司不太一样,做的事情方向也不同,可能是侧重点不同,一开始有些不适应,主要是压力上,会觉得压力比较大,但是总体来说与人相处的部分还是不错的,做的技术方向还是Java,这里也感谢前东家让我有机会转了Java,个人感觉杭州整个市场还是Java比较有优势,不过在开始的时候总觉得对Java有点不适应,应该值得深究的东西还是很多的,而且对于面试来说,也是有很多可以问的,后面慢慢发现除开某里等一线超一线互联网公司之外,大部分的面试还是有大概的套路跟大纲的,不过更细致的则因人而异了,面试有时候也还看缘分,面试官关注的点跟应试者比较契合的话就很容易通过面试,不然的话总会有能刁难或者理性化地说比较难回答的问题。这个后面可以单独说一下,先按下不表。
          刚进公司没多久就负责比较重要的项目,工期也比较紧张,整体来说那段时间的压力的确是比较大的,不过总算最后结果不坏,这里应该说对一些原来在前东家都是掌握的不太好的部分,比如maven,其实maven对于java程序员来说还是很重要的,但是我碰到过的面试基本没问过这个,我自己也在后面的面试中没问过相关的,不知道咋问,比如dependence分析、冲突解决,比如对bean的理解,这个算是我一直以来的疑问点,因为以前刚开始学Java学spring,上来就是bean,但是bean到底是啥,IOC是啥,可能网上的文章跟大多数书籍跟我的理解思路不太match,导致一直不能很好的理解这玩意,到后面才理解,要理解这个bean,需要有两个基本概念,一个是面向对象,一个是对象容器跟依赖反转,还是只说到这,后面可以有专题说一下,总之自认为技术上有了不小的长进了,方向上应该是偏实用的。这个重要的项目完成后慢慢能喘口气了,后面也有一些比较紧急且工作量大的,不过在我TL的帮助下还是能尽量协调好资源。

          +

          面试

          后面因为项目比较多,缺少开发,所以也参与帮忙做一些面试,这里总体感觉是面的候选人还是比较多样的,有些工作了蛮多年但是一些基础问题回答的不好,有些还是在校学生,但是面试技巧不错,针对常见的面试题都有不错的准备,不过还是觉得光靠这些面试题不能完全说明问题,真正工作了需要的是解决问题的人,而不是会背题的,退一步来说能好好准备面试还是比较重要的,也是双向选择中的基本尊重,印象比较深刻的是参加了去杭州某高校的校招面试,感觉参加校招的同学还是很多的,大部分是20年将毕业的研究生,挺多都是基础很扎实,对比起我刚要毕业时还是很汗颜,挺多来面试的同学都非常不错,那天强度也很大,从下午到那开始一直面到六七点,在这祝福那些来面试的同学,也都不容易的,能找到心仪的工作。

          +

          技术方向

          这一年前大半部分还是比较焦虑不能恢复那种主动找时间学习的状态,可能换了公司是主要的原因,初期有个适应的过程也比较正常,总体来说可能是到九十月份开始慢慢有所改善,对这些方面有学习了下,

          +
            +
          • spring方向,spring真的是个庞然大物,但是还是要先抓住根本,慢慢发散去了解其他的细节,抓住bean的生命周期,当然也不是死记硬背,让我一个个背下来我也不行,但是知道它究竟是干嘛的,有啥用,并且在工作中能用起来是最重要的
          • +
          • mysql数据库,这部分主要是关注了mvcc,知道了个大概,源码实现细节还没具体研究,有时间可以来个专题(一大堆待写的内容)
          • +
          • java的一些源码,比如aqs这种,结合文章看了下源码,一开始总感觉静不下心来看,然后有一次被LD刺激了下就看完了,包括conditionObject等
          • +
          • redis的源码,这里包括了Redis分布式锁和redis的数据结构源码,已经写成文章,不过比较着急成文,所以质量不是特别好,希望后面再来补补
          • +
          • jvm源码,这部分正好是想了解下g1收集器,大概把周志明的书看完了,但是还没完整的理解掌握,还有就是g1收集器的部分,一是概念部分大概理解了,后面是就是想从源码层面去学习理解,这也是新一年的主要计划
          • +
          • mq的部分是了解了zero copy,sendfile等,跟消息队列主题关系不大🤦‍♂️
            这么看还是学了点东西的,希望新一年再接再厉。
          • +
          +

          生活

          住的地方没变化,主要是周边设施比较方便,暂时没找到更好的就没打算换,主要的问题是没电梯,一开始没觉得有啥,真正住起来还是觉得比较累的,希望后面租的可以有电梯,或者楼层低一点,还有就是要通下水道,第一次让师傅上门,花了两百大洋,后来自学成才了,让师傅通了一次才撑了一个月就不行了,后面自己通的差不多可以撑半年,还是比较有成就感的😀,然后就是跑步了,年初的时候去了紫金港跑步,后面因为工作的原因没去了,但是公司的跑步机倒是让我重拾起这个唯一的运动健身项目,后面因为肠胃问题,体重也需要控制,所以就周末回来也在家这边坚持跑步,下半年的话基本保持每周一次以上,比较那些跑马拉松的大牛还是差距很大,不过也是突破自我了,有一次跑了12公里,最远的距离,而且后面感觉跑十公里也不是特别吃不消了,这一年达成了300公里的目标,体重也稍有下降,比较满意的结果。

          +

          期待

          希望工作方面技术方面能有所长进,生活上能多点时间陪家人,继续跑步减肥,家人健健康康的,嗯

          +]]>
          + + 生活 + 年终总结 + 2019 + + + 生活 + 年终总结 + 2019 + +
          2020 年终总结 /2021/03/31/2020-%E5%B9%B4%E7%BB%88%E6%80%BB%E7%BB%93/ @@ -64,35 +93,6 @@ 年中总结 - - 2019年终总结 - /2020/02/01/2019%E5%B9%B4%E7%BB%88%E6%80%BB%E7%BB%93/ - 今天是农历初八了,年前一个月的时候就准备做下今年的年终总结,可是写了一点觉得太情绪化了,希望后面写个平淡点的,正好最近技术方面还没有看到一个完整成文的内容,就来写一下这一年的总结,尽量少写一点太情绪化的东西。

          -

          跳槽

          年初换了个公司,也算换了个环境,跟前公司不太一样,做的事情方向也不同,可能是侧重点不同,一开始有些不适应,主要是压力上,会觉得压力比较大,但是总体来说与人相处的部分还是不错的,做的技术方向还是Java,这里也感谢前东家让我有机会转了Java,个人感觉杭州整个市场还是Java比较有优势,不过在开始的时候总觉得对Java有点不适应,应该值得深究的东西还是很多的,而且对于面试来说,也是有很多可以问的,后面慢慢发现除开某里等一线超一线互联网公司之外,大部分的面试还是有大概的套路跟大纲的,不过更细致的则因人而异了,面试有时候也还看缘分,面试官关注的点跟应试者比较契合的话就很容易通过面试,不然的话总会有能刁难或者理性化地说比较难回答的问题。这个后面可以单独说一下,先按下不表。
          刚进公司没多久就负责比较重要的项目,工期也比较紧张,整体来说那段时间的压力的确是比较大的,不过总算最后结果不坏,这里应该说对一些原来在前东家都是掌握的不太好的部分,比如maven,其实maven对于java程序员来说还是很重要的,但是我碰到过的面试基本没问过这个,我自己也在后面的面试中没问过相关的,不知道咋问,比如dependence分析、冲突解决,比如对bean的理解,这个算是我一直以来的疑问点,因为以前刚开始学Java学spring,上来就是bean,但是bean到底是啥,IOC是啥,可能网上的文章跟大多数书籍跟我的理解思路不太match,导致一直不能很好的理解这玩意,到后面才理解,要理解这个bean,需要有两个基本概念,一个是面向对象,一个是对象容器跟依赖反转,还是只说到这,后面可以有专题说一下,总之自认为技术上有了不小的长进了,方向上应该是偏实用的。这个重要的项目完成后慢慢能喘口气了,后面也有一些比较紧急且工作量大的,不过在我TL的帮助下还是能尽量协调好资源。

          -

          面试

          后面因为项目比较多,缺少开发,所以也参与帮忙做一些面试,这里总体感觉是面的候选人还是比较多样的,有些工作了蛮多年但是一些基础问题回答的不好,有些还是在校学生,但是面试技巧不错,针对常见的面试题都有不错的准备,不过还是觉得光靠这些面试题不能完全说明问题,真正工作了需要的是解决问题的人,而不是会背题的,退一步来说能好好准备面试还是比较重要的,也是双向选择中的基本尊重,印象比较深刻的是参加了去杭州某高校的校招面试,感觉参加校招的同学还是很多的,大部分是20年将毕业的研究生,挺多都是基础很扎实,对比起我刚要毕业时还是很汗颜,挺多来面试的同学都非常不错,那天强度也很大,从下午到那开始一直面到六七点,在这祝福那些来面试的同学,也都不容易的,能找到心仪的工作。

          -

          技术方向

          这一年前大半部分还是比较焦虑不能恢复那种主动找时间学习的状态,可能换了公司是主要的原因,初期有个适应的过程也比较正常,总体来说可能是到九十月份开始慢慢有所改善,对这些方面有学习了下,

          -
            -
          • spring方向,spring真的是个庞然大物,但是还是要先抓住根本,慢慢发散去了解其他的细节,抓住bean的生命周期,当然也不是死记硬背,让我一个个背下来我也不行,但是知道它究竟是干嘛的,有啥用,并且在工作中能用起来是最重要的
          • -
          • mysql数据库,这部分主要是关注了mvcc,知道了个大概,源码实现细节还没具体研究,有时间可以来个专题(一大堆待写的内容)
          • -
          • java的一些源码,比如aqs这种,结合文章看了下源码,一开始总感觉静不下心来看,然后有一次被LD刺激了下就看完了,包括conditionObject等
          • -
          • redis的源码,这里包括了Redis分布式锁和redis的数据结构源码,已经写成文章,不过比较着急成文,所以质量不是特别好,希望后面再来补补
          • -
          • jvm源码,这部分正好是想了解下g1收集器,大概把周志明的书看完了,但是还没完整的理解掌握,还有就是g1收集器的部分,一是概念部分大概理解了,后面是就是想从源码层面去学习理解,这也是新一年的主要计划
          • -
          • mq的部分是了解了zero copy,sendfile等,跟消息队列主题关系不大🤦‍♂️
            这么看还是学了点东西的,希望新一年再接再厉。
          • -
          -

          生活

          住的地方没变化,主要是周边设施比较方便,暂时没找到更好的就没打算换,主要的问题是没电梯,一开始没觉得有啥,真正住起来还是觉得比较累的,希望后面租的可以有电梯,或者楼层低一点,还有就是要通下水道,第一次让师傅上门,花了两百大洋,后来自学成才了,让师傅通了一次才撑了一个月就不行了,后面自己通的差不多可以撑半年,还是比较有成就感的😀,然后就是跑步了,年初的时候去了紫金港跑步,后面因为工作的原因没去了,但是公司的跑步机倒是让我重拾起这个唯一的运动健身项目,后面因为肠胃问题,体重也需要控制,所以就周末回来也在家这边坚持跑步,下半年的话基本保持每周一次以上,比较那些跑马拉松的大牛还是差距很大,不过也是突破自我了,有一次跑了12公里,最远的距离,而且后面感觉跑十公里也不是特别吃不消了,这一年达成了300公里的目标,体重也稍有下降,比较满意的结果。

          -

          期待

          希望工作方面技术方面能有所长进,生活上能多点时间陪家人,继续跑步减肥,家人健健康康的,嗯

          -]]>
          - - 生活 - 年终总结 - 2019 - - - 生活 - 年终总结 - 2019 - -
          34_Search_for_a_Range /2016/08/14/34-Search-for-a-Range/ @@ -139,29 +139,6 @@ public: c++ - - 2021 年中总结 - /2021/07/18/2021-%E5%B9%B4%E4%B8%AD%E6%80%BB%E7%BB%93/ - 又到半年总结时,第一次写总结类型的文章感觉挺好写的,但是后面总觉得这过去的一段时间所做的事情,能力上的成长低于预期,但是是需要总结下,找找问题,顺便展望下未来。

          -

          这一年做的最让自己满意的应该就是看了一些书,由折腾群洋总发起的读书打卡活动,到目前为止已经读完了这几本书,《cUrl 必知必会》,《古董局中局 1》,《古董局中局 2》,《算法图解》,《每天 5 分钟玩转 Kubernetes》《幸福了吗?》《高可用可伸缩微服务架构:基于 Dubbo、Spring Cloud和 Service Mesh》《Rust 权威指南》后面可以写个专题说说看的这些书,虽然每天打卡如果时间安排不好,并且看的书像 rust 这样比较难的话还是会有点小焦虑,不过也是个调整过程,一方面可以在白天就抽空看一会,然后也不必要每次都看很大一章,注重吸收。

          -

          技术上的成长的话,有一些比较小的长进吧,对于一些之前忽视的 synchronized,ThreadLocal 和 AQS 等知识点做了下查漏补缺了,然后多了解了一些 Java 垃圾回收的内容,但是在实操上还是比较欠缺,成型的技术方案,架构上所谓的优化也比较少,一些想法也还有考虑不周全的地方,还需要多花时间和心思去学习加强,特别是在目前已经有的基础上如何做系统深层次的优化,既不要是鸡毛蒜皮的,也不能出现一些不可接受的问题和故障,这是个很重要的课题,需要好好学习,后面考虑定一些周期性目标,两个月左右能有一些成果和总结。

          -

          另外一部分是自己的服务,因为 ucloud 的机器太贵就没续费了,所以都迁移到腾讯云的小机器上了,顺便折腾了一点点 traefik,但是还很不熟练,不太习惯这一套,一方面是 docker 还不习惯,这也加重了对这套环境的不适应,还是习惯裸机部署,另一方面就是 k8s 了,家里的机器还没虚拟化,没有很好的条件可以做实验,这也是读书打卡的一个没做好的点,整体的学习效果受限于深度和实操,后面是看都是用 traefik,也找到了一篇文章可以 traefik 转发到裸机应用,因为主仓库用的是裸机的 gogs。

          -

          还有就是运动减肥上,唉,这又是很大的一个痛点,基本没效果,只是还算稳定,昨天看到一个视频说还需要力量训练来增肌,以此可以提升基础代谢,打算往这个方向尝试下,因为今天没有疫情限制了,在 6 月底完成了 200 公里的跑步小目标,只是有些膝盖跟大腿根外侧不适,抽空得去看下医生,后面打算每天也能做点卷腹跟俯卧撑。

          -

          下半年还希望能继续多看看书,比很多网上各种乱七八糟的文章会好很多,结合豆瓣评分,找一些评价高一些的文章,但也不是说分稍低点的就不行,有些也看人是不是适合,一般 6 分以上评价比较多的就可以试试。

          -]]>
          - - 生活 - 年中总结 - 2021 - - - 生活 - 2021 - 年中总结 - 技术 - 读书 - -
          AQS篇二 之 Condition 浅析笔记 /2021/02/21/AQS-%E4%B9%8B-Condition-%E6%B5%85%E6%9E%90%E7%AC%94%E8%AE%B0/ @@ -660,288 +637,66 @@ public: - 2021 年终总结 - /2022/01/22/2021-%E5%B9%B4%E7%BB%88%E6%80%BB%E7%BB%93/ - 又是一年年终总结,本着极度讨厌实时需求的理念,我还是 T+N 发布这个年终总结

          -

          工作篇

          工作没什么大变化,有了些微的提升,可能因为是来了之后做了些项目对比公司与来还算是比较重要的,但是技术难度上没有特别突出的点,可能最开始用 openresty+lua 做了个 ab 测的工具,还是让我比较满意的,后面一般都是业务型的需求,今年可能在业务相关的技术逻辑上有了一些深度的了解,而原来一直想做的业务架构升级和通用型技术中间件这样的优化还是停留在想象中,前面说的 ab 测应该算是个半成品,还是没能多走出这一步,得需要多做一些实在的事情,比如轻量级的业务框架,能够对原先不熟悉的业务逻辑,代码逻辑有比较深入的理解,而不是一直都是让特定的同学负责特定的逻辑,很多时候还是在偷懒,习惯以一些简单安全的方案去做事情,在技术上还是要有所追求,还有就是能够在新语言,主要是 rust,swift 这类的能有些小玩具可以做,rust 的话是因为今年看了一本相关的书,后面三分之一其实消化得不好,这本书整体来说是很不错的,只是 rust 本身在所有权这块,还有引用包装等方面是设计得比较难懂,也可能是我基础差,所以还是想在复习下,可以做一个简单的命令行工具这种,然后 swift 是想说可以做点 mac 的小软件,原生的毕竟性能好点,又小。基于 web 做的客户端大部分都是又丑又大,极少数能好看点,但也是很重,起码 7~80M 的大小,原生的估计能除以 10。
          整体的职业规划貌似陷入了比较大的困惑期,在目前公司发展前景不是很大,但是出去貌似也没有比较适合我的机会,总的来说还是杭州比较卷,个人觉得有自己的时间是非常重要的,而且这个不光是用来自我提升的,还是让自己有足够的时间做缓冲,有足够的时间锻炼减肥,时间少的情况下,不光会在仅有的时间里暴饮暴食,还没空锻炼,身体是革命的本钱,现在其实能特别明显地感觉到身体状态下滑,容易疲劳,焦虑。所以是否也许有可能以后要往外企这类的方向去发展。
          工作上其实还是有个不大不小的缺点,就是容易激动,容易焦虑,前一点可能有稍稍地改观,因为工作中的很多现状其实是我个人难以改变的,即使觉得不合理,但是结构在那里,还不如自己放宽心,尽量做好事情就行。第二点的话还是做得比较差,一直以来抗压能力都比较差,跟成长环境,家庭环境都有比较大的关系,而且说实在的特别是父母,基本也没有在这方面给我正向的帮助,比较擅长给我施压,从小就是通过压力让我好好读书,当个乖学生,考个好学校,并没有能真正地理解我的压力,教我或者帮助我解压,只会在那说着不着边际的空话,甚至经常反过来对我施压。还是希望能慢慢解开,这点可能对我身体也有影响,也许需要看一些心理疏导相关的书籍。工作篇暂时到这,后续还有其他篇,未完待续哈哈😀

          + 2021 年中总结 + /2021/07/18/2021-%E5%B9%B4%E4%B8%AD%E6%80%BB%E7%BB%93/ + 又到半年总结时,第一次写总结类型的文章感觉挺好写的,但是后面总觉得这过去的一段时间所做的事情,能力上的成长低于预期,但是是需要总结下,找找问题,顺便展望下未来。

          +

          这一年做的最让自己满意的应该就是看了一些书,由折腾群洋总发起的读书打卡活动,到目前为止已经读完了这几本书,《cUrl 必知必会》,《古董局中局 1》,《古董局中局 2》,《算法图解》,《每天 5 分钟玩转 Kubernetes》《幸福了吗?》《高可用可伸缩微服务架构:基于 Dubbo、Spring Cloud和 Service Mesh》《Rust 权威指南》后面可以写个专题说说看的这些书,虽然每天打卡如果时间安排不好,并且看的书像 rust 这样比较难的话还是会有点小焦虑,不过也是个调整过程,一方面可以在白天就抽空看一会,然后也不必要每次都看很大一章,注重吸收。

          +

          技术上的成长的话,有一些比较小的长进吧,对于一些之前忽视的 synchronized,ThreadLocal 和 AQS 等知识点做了下查漏补缺了,然后多了解了一些 Java 垃圾回收的内容,但是在实操上还是比较欠缺,成型的技术方案,架构上所谓的优化也比较少,一些想法也还有考虑不周全的地方,还需要多花时间和心思去学习加强,特别是在目前已经有的基础上如何做系统深层次的优化,既不要是鸡毛蒜皮的,也不能出现一些不可接受的问题和故障,这是个很重要的课题,需要好好学习,后面考虑定一些周期性目标,两个月左右能有一些成果和总结。

          +

          另外一部分是自己的服务,因为 ucloud 的机器太贵就没续费了,所以都迁移到腾讯云的小机器上了,顺便折腾了一点点 traefik,但是还很不熟练,不太习惯这一套,一方面是 docker 还不习惯,这也加重了对这套环境的不适应,还是习惯裸机部署,另一方面就是 k8s 了,家里的机器还没虚拟化,没有很好的条件可以做实验,这也是读书打卡的一个没做好的点,整体的学习效果受限于深度和实操,后面是看都是用 traefik,也找到了一篇文章可以 traefik 转发到裸机应用,因为主仓库用的是裸机的 gogs。

          +

          还有就是运动减肥上,唉,这又是很大的一个痛点,基本没效果,只是还算稳定,昨天看到一个视频说还需要力量训练来增肌,以此可以提升基础代谢,打算往这个方向尝试下,因为今天没有疫情限制了,在 6 月底完成了 200 公里的跑步小目标,只是有些膝盖跟大腿根外侧不适,抽空得去看下医生,后面打算每天也能做点卷腹跟俯卧撑。

          +

          下半年还希望能继续多看看书,比很多网上各种乱七八糟的文章会好很多,结合豆瓣评分,找一些评价高一些的文章,但也不是说分稍低点的就不行,有些也看人是不是适合,一般 6 分以上评价比较多的就可以试试。

          ]]>
          生活 - 年终总结 + 年中总结 + 2021 生活 - 年终总结 2021 - 拖更 + 年中总结 + 技术 + 读书
          - AQS篇一 - /2021/02/14/AQS%E7%AF%87%E4%B8%80/ - 很多东西都是时看时新,而且时间长了也会忘,所以再来复习下,也会有一些新的角度看法这次来聊下AQS的内容,主要是这几个点,

          -

          第一个线程

          第一个线程抢到锁了,此时state跟阻塞队列是怎么样的,其实这里是之前没理解对的地方

          -
          /**
          -         * Fair version of tryAcquire.  Don't grant access unless
          -         * recursive call or no waiters or is first.
          -         */
          -        protected final boolean tryAcquire(int acquires) {
          -            final Thread current = Thread.currentThread();
          -            int c = getState();
          -            // 这里如果state还是0说明锁还空着
          -            if (c == 0) {
          -                // 因为是公平锁版本的,先去看下是否阻塞队列里有排着队的
          -                if (!hasQueuedPredecessors() &&
          -                    compareAndSetState(0, acquires)) {
          -                    // 没有排队的,并且state使用cas设置成功的就标记当前占有锁的线程是我
          -                    setExclusiveOwnerThread(current);
          -                    // 然后其实就返回了,包括阻塞队列的head和tail节点和waitStatus都没有设置
          -                    return true;
          -                }
          -            }
          -            else if (current == getExclusiveOwnerThread()) {
          -                int nextc = c + acquires;
          -                if (nextc < 0)
          -                    throw new Error("Maximum lock count exceeded");
          -                setState(nextc);
          -                return true;
          -            }
          -            // 这里就是第二个线程会返回false
          -            return false;
          -        }
          -    }
          + AbstractQueuedSynchronizer + /2019/09/23/AbstractQueuedSynchronizer/ + 最近看了大神的 AQS 的文章,之前总是断断续续地看一点,每次都知难而退,下次看又从头开始,昨天总算硬着头皮看完了第一部分
          首先 AQS 只要有这些属性

          +
          // 头结点,你直接把它当做 当前持有锁的线程 可能是最好理解的
          +private transient volatile Node head;
           
          -

          第二个线程

          当第二个线程进来的时候应该是怎么样,结合代码来看

          -
          /**
          -     * Acquires in exclusive mode, ignoring interrupts.  Implemented
          -     * by invoking at least once {@link #tryAcquire},
          -     * returning on success.  Otherwise the thread is queued, possibly
          -     * repeatedly blocking and unblocking, invoking {@link
          -     * #tryAcquire} until success.  This method can be used
          -     * to implement method {@link Lock#lock}.
          -     *
          -     * @param arg the acquire argument.  This value is conveyed to
          -     *        {@link #tryAcquire} but is otherwise uninterpreted and
          -     *        can represent anything you like.
          -     */
          -    public final void acquire(int arg) {
          -        // 前面第一种情况是tryAcquire直接成功了,这个if判断第一个条件就是false,就不往下执行了
          -        // 如果是第二个线程,第一个条件获取锁不成功,条件判断!tryAcquire(arg) == true,就会走
          -        // acquireQueued(addWaiter(Node.EXCLUSIVE), arg)
          -        if (!tryAcquire(arg) &&
          -            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
          -            selfInterrupt();
          -    }
          +// 阻塞的尾节点,每个新的节点进来,都插入到最后,也就形成了一个链表 +private transient volatile Node tail; -

          然后来看下addWaiter的逻辑

          -
          /**
          -     * Creates and enqueues node for current thread and given mode.
          -     *
          -     * @param mode Node.EXCLUSIVE for exclusive, Node.SHARED for shared
          -     * @return the new node
          -     */
          -    private Node addWaiter(Node mode) {
          -        // 这里是包装成一个node
          -        Node node = new Node(Thread.currentThread(), mode);
          -        // Try the fast path of enq; backup to full enq on failure
          -        // 最快的方式就是把当前线程的节点放在阻塞队列的最后
          -        Node pred = tail;
          -        // 只有当tail,也就是pred不为空的时候可以直接接上
          -        if (pred != null) {
          -            node.prev = pred;
          -            // 如果这里cas成功了,就直接接上返回了
          -            if (compareAndSetTail(pred, node)) {
          -                pred.next = node;
          -                return node;
          -            }
          -        }
          -        // 不然就会继续走到这里
          -        enq(node);
          -        return node;
          -    }
          +// 这个是最重要的,代表当前锁的状态,0代表没有被占用,大于 0 代表有线程持有当前锁 +// 这个值可以大于 1,是因为锁可以重入,每次重入都加上 1 +private volatile int state; -

          然后就是enq的逻辑了

          -
          /**
          -     * Inserts node into queue, initializing if necessary. See picture above.
          -     * @param node the node to insert
          -     * @return node's predecessor
          -     */
          -    private Node enq(final Node node) {
          -        for (;;) {
          -            // 如果状态没变化的话,tail这时还是null的
          -            Node t = tail;
          -            if (t == null) { // Must initialize
          -                // 这里就会初始化头结点,就是个空节点
          -                if (compareAndSetHead(new Node()))
          -                    // tail也赋值成head
          -                    tail = head;
          -            } else {
          -                // 这里就设置tail了
          -                node.prev = t;
          -                if (compareAndSetTail(t, node)) {
          -                    t.next = node;
          -                    return t;
          -                }
          -            }
          -        }
          -    }
          +// 代表当前持有独占锁的线程,举个最重要的使用例子,因为锁可以重入 +// reentrantLock.lock()可以嵌套调用多次,所以每次用这个来判断当前线程是否已经拥有了锁 +// if (currentThread == getExclusiveOwnerThread()) {state++} +private transient Thread exclusiveOwnerThread; //继承自AbstractOwnableSynchronizer
          +

          大概了解了 aqs 底层的双向等待队列,
          结构是这样的

          每个 node 里面主要是的代码结构也比较简单

          +
          static final class Node {
          +    // 标识节点当前在共享模式下
          +    static final Node SHARED = new Node();
          +    // 标识节点当前在独占模式下
          +    static final Node EXCLUSIVE = null;
           
          -

          所以从这里可以看出来,其实head头结点不是个真实的带有线程的节点,并且不是在第一个线程进来的时候设置的

          -

          解锁

          通过代码来看下

          -
          /**
          -     * Attempts to release this lock.
          -     *
          -     * <p>If the current thread is the holder of this lock then the hold
          -     * count is decremented.  If the hold count is now zero then the lock
          -     * is released.  If the current thread is not the holder of this
          -     * lock then {@link IllegalMonitorStateException} is thrown.
          -     *
          -     * @throws IllegalMonitorStateException if the current thread does not
          -     *         hold this lock
          -     */
          -    public void unlock() {
          -        // 释放锁
          -        sync.release(1);
          -    }
          -/**
          -     * Releases in exclusive mode.  Implemented by unblocking one or
          -     * more threads if {@link #tryRelease} returns true.
          -     * This method can be used to implement method {@link Lock#unlock}.
          -     *
          -     * @param arg the release argument.  This value is conveyed to
          -     *        {@link #tryRelease} but is otherwise uninterpreted and
          -     *        can represent anything you like.
          -     * @return the value returned from {@link #tryRelease}
          -     */
          -    public final boolean release(int arg) {
          -        // 尝试去释放
          -        if (tryRelease(arg)) {
          -            Node h = head;
          -            if (h != null && h.waitStatus != 0)
          -                unparkSuccessor(h);
          -            return true;
          -        }
          -        return false;
          -    }
          -protected final boolean tryRelease(int releases) {
          -            int c = getState() - releases;
          -            if (Thread.currentThread() != getExclusiveOwnerThread())
          -                throw new IllegalMonitorStateException();
          -            boolean free = false;
          -    		// 判断是否完全释放锁,因为可重入
          -            if (c == 0) {
          -                free = true;
          -                setExclusiveOwnerThread(null);
          -            }
          -            setState(c);
          -            return free;
          -        }
          -// 这段代码和上面的一致,只是为了顺序性,又拷下来看下
          -
          -public final boolean release(int arg) {
          -        // 尝试去释放,如果是完全释放,返回的就是true,否则是false
          -        if (tryRelease(arg)) {
          -            Node h = head;
          -            // 这里判断头结点是否为空以及waitStatus的状态,前面说了head节点其实是
          -            // 在第二个线程进来的时候初始化的,如果是空的话说明没后续节点,并且waitStatus
          -            // 也表示了后续的等待状态
          -            if (h != null && h.waitStatus != 0)
          -                unparkSuccessor(h);
          -            return true;
          -        }
          -        return false;
          -    }
          -
          -/**
          -     * Wakes up node's successor, if one exists.
          -     *
          -     * @param node the node
          -     */
          -// 唤醒后继节点
          -    private void unparkSuccessor(Node node) {
          -        /*
          -         * If status is negative (i.e., possibly needing signal) try
          -         * to clear in anticipation of signalling.  It is OK if this
          -         * fails or if status is changed by waiting thread.
          -         */
          -        int ws = node.waitStatus;
          -        if (ws < 0)
          -            compareAndSetWaitStatus(node, ws, 0);
          -
          -        /*
          -         * Thread to unpark is held in successor, which is normally
          -         * just the next node.  But if cancelled or apparently null,
          -         * traverse backwards from tail to find the actual
          -         * non-cancelled successor.
          -         */
          -        Node s = node.next;
          -        // 如果后继节点是空或者当前节点取消等待了
          -        if (s == null || s.waitStatus > 0) {
          -            s = null;
          -            // 从后往前找,找到非取消的节点,注意这里不是找到就退出,而是一直找到头
          -            // 所以不必担心中间有取消的
          -            for (Node t = tail; t != null && t != node; t = t.prev)
          -                if (t.waitStatus <= 0)
          -                    s = t;
          -        }
          -        if (s != null)
          -            // 将其唤醒
          -            LockSupport.unpark(s.thread);
          -    }
          - - - - -]]> - - Java - 并发 - - - java - 并发 - j.u.c - aqs - - - - AbstractQueuedSynchronizer - /2019/09/23/AbstractQueuedSynchronizer/ - 最近看了大神的 AQS 的文章,之前总是断断续续地看一点,每次都知难而退,下次看又从头开始,昨天总算硬着头皮看完了第一部分
          首先 AQS 只要有这些属性

          -
          // 头结点,你直接把它当做 当前持有锁的线程 可能是最好理解的
          -private transient volatile Node head;
          -
          -// 阻塞的尾节点,每个新的节点进来,都插入到最后,也就形成了一个链表
          -private transient volatile Node tail;
          -
          -// 这个是最重要的,代表当前锁的状态,0代表没有被占用,大于 0 代表有线程持有当前锁
          -// 这个值可以大于 1,是因为锁可以重入,每次重入都加上 1
          -private volatile int state;
          -
          -// 代表当前持有独占锁的线程,举个最重要的使用例子,因为锁可以重入
          -// reentrantLock.lock()可以嵌套调用多次,所以每次用这个来判断当前线程是否已经拥有了锁
          -// if (currentThread == getExclusiveOwnerThread()) {state++}
          -private transient Thread exclusiveOwnerThread; //继承自AbstractOwnableSynchronizer
          -

          大概了解了 aqs 底层的双向等待队列,
          结构是这样的

          每个 node 里面主要是的代码结构也比较简单

          -
          static final class Node {
          -    // 标识节点当前在共享模式下
          -    static final Node SHARED = new Node();
          -    // 标识节点当前在独占模式下
          -    static final Node EXCLUSIVE = null;
          -
          -    // ======== 下面的几个int常量是给waitStatus用的 ===========
          -    /** waitStatus value to indicate thread has cancelled */
          -    // 代码此线程取消了争抢这个锁
          -    static final int CANCELLED =  1;
          -    /** waitStatus value to indicate successor's thread needs unparking */
          -    // 官方的描述是,其表示当前node的后继节点对应的线程需要被唤醒
          -    static final int SIGNAL    = -1;
          -    /** waitStatus value to indicate thread is waiting on condition */
          -    // 本文不分析condition,所以略过吧,下一篇文章会介绍这个
          -    static final int CONDITION = -2;
          -    /**
          -     * waitStatus value to indicate the next acquireShared should
          -     * unconditionally propagate
          +    // ======== 下面的几个int常量是给waitStatus用的 ===========
          +    /** waitStatus value to indicate thread has cancelled */
          +    // 代码此线程取消了争抢这个锁
          +    static final int CANCELLED =  1;
          +    /** waitStatus value to indicate successor's thread needs unparking */
          +    // 官方的描述是,其表示当前node的后继节点对应的线程需要被唤醒
          +    static final int SIGNAL    = -1;
          +    /** waitStatus value to indicate thread is waiting on condition */
          +    // 本文不分析condition,所以略过吧,下一篇文章会介绍这个
          +    static final int CONDITION = -2;
          +    /**
          +     * waitStatus value to indicate the next acquireShared should
          +     * unconditionally propagate
                */
               // 同样的不分析,略过吧
               static final int PROPAGATE = -3;
          @@ -1074,90 +829,248 @@ public:
                 
             
             
          -    Apollo 的 value 注解是怎么自动更新的
          -    /2020/11/01/Apollo-%E7%9A%84-value-%E6%B3%A8%E8%A7%A3%E6%98%AF%E6%80%8E%E4%B9%88%E8%87%AA%E5%8A%A8%E6%9B%B4%E6%96%B0%E7%9A%84/
          -    在前司和目前公司,用的配置中心都是使用的 Apollo,经过了业界验证,比较强大的配置管理系统,特别是在0.10 后开始支持对使用 value 注解的配置值进行自动更新,今天刚好有个同学问到我,就顺便写篇文章记录下,其实也是借助于 spring 强大的 bean 生命周期管理,可以实现BeanPostProcessor接口,使用postProcessBeforeInitialization方法,来对bean 内部的属性和方法进行判断,是否有 value 注解,如果有就是将它注册到一个 map 中,可以看到这个方法com.ctrip.framework.apollo.spring.annotation.SpringValueProcessor#processField

          -
          @Override
          -  protected void processField(Object bean, String beanName, Field field) {
          -    // register @Value on field
          -    Value value = field.getAnnotation(Value.class);
          -    if (value == null) {
          -      return;
          -    }
          -    Set<String> keys = placeholderHelper.extractPlaceholderKeys(value.value());
          -
          -    if (keys.isEmpty()) {
          -      return;
          -    }
          +    AQS篇一
          +    /2021/02/14/AQS%E7%AF%87%E4%B8%80/
          +    很多东西都是时看时新,而且时间长了也会忘,所以再来复习下,也会有一些新的角度看法这次来聊下AQS的内容,主要是这几个点,

          +

          第一个线程

          第一个线程抢到锁了,此时state跟阻塞队列是怎么样的,其实这里是之前没理解对的地方

          +
          /**
          +         * Fair version of tryAcquire.  Don't grant access unless
          +         * recursive call or no waiters or is first.
          +         */
          +        protected final boolean tryAcquire(int acquires) {
          +            final Thread current = Thread.currentThread();
          +            int c = getState();
          +            // 这里如果state还是0说明锁还空着
          +            if (c == 0) {
          +                // 因为是公平锁版本的,先去看下是否阻塞队列里有排着队的
          +                if (!hasQueuedPredecessors() &&
          +                    compareAndSetState(0, acquires)) {
          +                    // 没有排队的,并且state使用cas设置成功的就标记当前占有锁的线程是我
          +                    setExclusiveOwnerThread(current);
          +                    // 然后其实就返回了,包括阻塞队列的head和tail节点和waitStatus都没有设置
          +                    return true;
          +                }
          +            }
          +            else if (current == getExclusiveOwnerThread()) {
          +                int nextc = c + acquires;
          +                if (nextc < 0)
          +                    throw new Error("Maximum lock count exceeded");
          +                setState(nextc);
          +                return true;
          +            }
          +            // 这里就是第二个线程会返回false
          +            return false;
          +        }
          +    }
          - for (String key : keys) { - SpringValue springValue = new SpringValue(key, value.value(), bean, beanName, field, false); - springValueRegistry.register(beanFactory, key, springValue); - logger.debug("Monitoring {}", springValue); - } - }
          -

          然后我们看下这个springValueRegistry是啥玩意

          -
          public class SpringValueRegistry {
          -  private static final long CLEAN_INTERVAL_IN_SECONDS = 5;
          -  private final Map<BeanFactory, Multimap<String, SpringValue>> registry = Maps.newConcurrentMap();
          -  private final AtomicBoolean initialized = new AtomicBoolean(false);
          -  private final Object LOCK = new Object();
          +

          第二个线程

          当第二个线程进来的时候应该是怎么样,结合代码来看

          +
          /**
          +     * Acquires in exclusive mode, ignoring interrupts.  Implemented
          +     * by invoking at least once {@link #tryAcquire},
          +     * returning on success.  Otherwise the thread is queued, possibly
          +     * repeatedly blocking and unblocking, invoking {@link
          +     * #tryAcquire} until success.  This method can be used
          +     * to implement method {@link Lock#lock}.
          +     *
          +     * @param arg the acquire argument.  This value is conveyed to
          +     *        {@link #tryAcquire} but is otherwise uninterpreted and
          +     *        can represent anything you like.
          +     */
          +    public final void acquire(int arg) {
          +        // 前面第一种情况是tryAcquire直接成功了,这个if判断第一个条件就是false,就不往下执行了
          +        // 如果是第二个线程,第一个条件获取锁不成功,条件判断!tryAcquire(arg) == true,就会走
          +        // acquireQueued(addWaiter(Node.EXCLUSIVE), arg)
          +        if (!tryAcquire(arg) &&
          +            acquireQueued(addWaiter(Node.EXCLUSIVE), arg))
          +            selfInterrupt();
          +    }
          - public void register(BeanFactory beanFactory, String key, SpringValue springValue) { - if (!registry.containsKey(beanFactory)) { - synchronized (LOCK) { - if (!registry.containsKey(beanFactory)) { - registry.put(beanFactory, LinkedListMultimap.<String, SpringValue>create()); +

          然后来看下addWaiter的逻辑

          +
          /**
          +     * Creates and enqueues node for current thread and given mode.
          +     *
          +     * @param mode Node.EXCLUSIVE for exclusive, Node.SHARED for shared
          +     * @return the new node
          +     */
          +    private Node addWaiter(Node mode) {
          +        // 这里是包装成一个node
          +        Node node = new Node(Thread.currentThread(), mode);
          +        // Try the fast path of enq; backup to full enq on failure
          +        // 最快的方式就是把当前线程的节点放在阻塞队列的最后
          +        Node pred = tail;
          +        // 只有当tail,也就是pred不为空的时候可以直接接上
          +        if (pred != null) {
          +            node.prev = pred;
          +            // 如果这里cas成功了,就直接接上返回了
          +            if (compareAndSetTail(pred, node)) {
          +                pred.next = node;
          +                return node;
          +            }
                   }
          -      }
          -    }
          -
          -    registry.get(beanFactory).put(key, springValue);
          +        // 不然就会继续走到这里
          +        enq(node);
          +        return node;
          +    }
          - // lazy initialize - if (initialized.compareAndSet(false, true)) { - initialize(); +

          然后就是enq的逻辑了

          +
          /**
          +     * Inserts node into queue, initializing if necessary. See picture above.
          +     * @param node the node to insert
          +     * @return node's predecessor
          +     */
          +    private Node enq(final Node node) {
          +        for (;;) {
          +            // 如果状态没变化的话,tail这时还是null的
          +            Node t = tail;
          +            if (t == null) { // Must initialize
          +                // 这里就会初始化头结点,就是个空节点
          +                if (compareAndSetHead(new Node()))
          +                    // tail也赋值成head
          +                    tail = head;
          +            } else {
          +                // 这里就设置tail了
          +                node.prev = t;
          +                if (compareAndSetTail(t, node)) {
          +                    t.next = node;
          +                    return t;
          +                }
          +            }
          +        }
          +    }
          + +

          所以从这里可以看出来,其实head头结点不是个真实的带有线程的节点,并且不是在第一个线程进来的时候设置的

          +

          解锁

          通过代码来看下

          +
          /**
          +     * Attempts to release this lock.
          +     *
          +     * <p>If the current thread is the holder of this lock then the hold
          +     * count is decremented.  If the hold count is now zero then the lock
          +     * is released.  If the current thread is not the holder of this
          +     * lock then {@link IllegalMonitorStateException} is thrown.
          +     *
          +     * @throws IllegalMonitorStateException if the current thread does not
          +     *         hold this lock
          +     */
          +    public void unlock() {
          +        // 释放锁
          +        sync.release(1);
               }
          -  }
          -

          这类其实就是个 map 来存放 springvalue,然后有com.ctrip.framework.apollo.spring.property.AutoUpdateConfigChangeListener来监听更新操作,当有变更时

          -
          @Override
          - public void onChange(ConfigChangeEvent changeEvent) {
          -   Set<String> keys = changeEvent.changedKeys();
          -   if (CollectionUtils.isEmpty(keys)) {
          -     return;
          -   }
          -   for (String key : keys) {
          -     // 1. check whether the changed key is relevant
          -     Collection<SpringValue> targetValues = springValueRegistry.get(beanFactory, key);
          -     if (targetValues == null || targetValues.isEmpty()) {
          -       continue;
          -     }
          +/**
          +     * Releases in exclusive mode.  Implemented by unblocking one or
          +     * more threads if {@link #tryRelease} returns true.
          +     * This method can be used to implement method {@link Lock#unlock}.
          +     *
          +     * @param arg the release argument.  This value is conveyed to
          +     *        {@link #tryRelease} but is otherwise uninterpreted and
          +     *        can represent anything you like.
          +     * @return the value returned from {@link #tryRelease}
          +     */
          +    public final boolean release(int arg) {
          +        // 尝试去释放
          +        if (tryRelease(arg)) {
          +            Node h = head;
          +            if (h != null && h.waitStatus != 0)
          +                unparkSuccessor(h);
          +            return true;
          +        }
          +        return false;
          +    }
          +protected final boolean tryRelease(int releases) {
          +            int c = getState() - releases;
          +            if (Thread.currentThread() != getExclusiveOwnerThread())
          +                throw new IllegalMonitorStateException();
          +            boolean free = false;
          +    		// 判断是否完全释放锁,因为可重入
          +            if (c == 0) {
          +                free = true;
          +                setExclusiveOwnerThread(null);
          +            }
          +            setState(c);
          +            return free;
          +        }
          +// 这段代码和上面的一致,只是为了顺序性,又拷下来看下
          +
          +public final boolean release(int arg) {
          +        // 尝试去释放,如果是完全释放,返回的就是true,否则是false
          +        if (tryRelease(arg)) {
          +            Node h = head;
          +            // 这里判断头结点是否为空以及waitStatus的状态,前面说了head节点其实是
          +            // 在第二个线程进来的时候初始化的,如果是空的话说明没后续节点,并且waitStatus
          +            // 也表示了后续的等待状态
          +            if (h != null && h.waitStatus != 0)
          +                unparkSuccessor(h);
          +            return true;
          +        }
          +        return false;
          +    }
          +
          +/**
          +     * Wakes up node's successor, if one exists.
          +     *
          +     * @param node the node
          +     */
          +// 唤醒后继节点
          +    private void unparkSuccessor(Node node) {
          +        /*
          +         * If status is negative (i.e., possibly needing signal) try
          +         * to clear in anticipation of signalling.  It is OK if this
          +         * fails or if status is changed by waiting thread.
          +         */
          +        int ws = node.waitStatus;
          +        if (ws < 0)
          +            compareAndSetWaitStatus(node, ws, 0);
          +
          +        /*
          +         * Thread to unpark is held in successor, which is normally
          +         * just the next node.  But if cancelled or apparently null,
          +         * traverse backwards from tail to find the actual
          +         * non-cancelled successor.
          +         */
          +        Node s = node.next;
          +        // 如果后继节点是空或者当前节点取消等待了
          +        if (s == null || s.waitStatus > 0) {
          +            s = null;
          +            // 从后往前找,找到非取消的节点,注意这里不是找到就退出,而是一直找到头
          +            // 所以不必担心中间有取消的
          +            for (Node t = tail; t != null && t != node; t = t.prev)
          +                if (t.waitStatus <= 0)
          +                    s = t;
          +        }
          +        if (s != null)
          +            // 将其唤醒
          +            LockSupport.unpark(s.thread);
          +    }
          + + - // 2. check whether the value is really changed or not (since spring property sources have hierarchies) - // 这里其实有一点比较绕,是因为 Apollo 里的 namespace 划分,会出现 key 相同,但是 namespace 不同的情况,所以会有个优先级存在,所以需要去校验 environment 里面的是否已经更新,如果未更新则表示不需要更新 - if (!shouldTriggerAutoUpdate(changeEvent, key)) { - continue; - } - // 3. update the value - for (SpringValue val : targetValues) { - updateSpringValue(val); - } - } - }
          -

          其实原理很简单,就是得了解知道下

          ]]>
          Java - Apollo - value + 并发 - Java - Apollo - value - 注解 - environment + java + 并发 + j.u.c + aqs + +
          + + 2021 年终总结 + /2022/01/22/2021-%E5%B9%B4%E7%BB%88%E6%80%BB%E7%BB%93/ + 又是一年年终总结,本着极度讨厌实时需求的理念,我还是 T+N 发布这个年终总结

          +

          工作篇

          工作没什么大变化,有了些微的提升,可能因为是来了之后做了些项目对比公司与来还算是比较重要的,但是技术难度上没有特别突出的点,可能最开始用 openresty+lua 做了个 ab 测的工具,还是让我比较满意的,后面一般都是业务型的需求,今年可能在业务相关的技术逻辑上有了一些深度的了解,而原来一直想做的业务架构升级和通用型技术中间件这样的优化还是停留在想象中,前面说的 ab 测应该算是个半成品,还是没能多走出这一步,得需要多做一些实在的事情,比如轻量级的业务框架,能够对原先不熟悉的业务逻辑,代码逻辑有比较深入的理解,而不是一直都是让特定的同学负责特定的逻辑,很多时候还是在偷懒,习惯以一些简单安全的方案去做事情,在技术上还是要有所追求,还有就是能够在新语言,主要是 rust,swift 这类的能有些小玩具可以做,rust 的话是因为今年看了一本相关的书,后面三分之一其实消化得不好,这本书整体来说是很不错的,只是 rust 本身在所有权这块,还有引用包装等方面是设计得比较难懂,也可能是我基础差,所以还是想在复习下,可以做一个简单的命令行工具这种,然后 swift 是想说可以做点 mac 的小软件,原生的毕竟性能好点,又小。基于 web 做的客户端大部分都是又丑又大,极少数能好看点,但也是很重,起码 7~80M 的大小,原生的估计能除以 10。
          整体的职业规划貌似陷入了比较大的困惑期,在目前公司发展前景不是很大,但是出去貌似也没有比较适合我的机会,总的来说还是杭州比较卷,个人觉得有自己的时间是非常重要的,而且这个不光是用来自我提升的,还是让自己有足够的时间做缓冲,有足够的时间锻炼减肥,时间少的情况下,不光会在仅有的时间里暴饮暴食,还没空锻炼,身体是革命的本钱,现在其实能特别明显地感觉到身体状态下滑,容易疲劳,焦虑。所以是否也许有可能以后要往外企这类的方向去发展。
          工作上其实还是有个不大不小的缺点,就是容易激动,容易焦虑,前一点可能有稍稍地改观,因为工作中的很多现状其实是我个人难以改变的,即使觉得不合理,但是结构在那里,还不如自己放宽心,尽量做好事情就行。第二点的话还是做得比较差,一直以来抗压能力都比较差,跟成长环境,家庭环境都有比较大的关系,而且说实在的特别是父母,基本也没有在这方面给我正向的帮助,比较擅长给我施压,从小就是通过压力让我好好读书,当个乖学生,考个好学校,并没有能真正地理解我的压力,教我或者帮助我解压,只会在那说着不着边际的空话,甚至经常反过来对我施压。还是希望能慢慢解开,这点可能对我身体也有影响,也许需要看一些心理疏导相关的书籍。工作篇暂时到这,后续还有其他篇,未完待续哈哈😀

          +]]>
          + + 生活 + 年终总结 + + + 生活 + 年终总结 + 2021 + 拖更
          @@ -1214,57 +1127,144 @@ Node *clone(Node *graph) { - Comparator使用小记 - /2020/04/05/Comparator%E4%BD%BF%E7%94%A8%E5%B0%8F%E8%AE%B0/ - 在Java8的stream之前,将对象进行排序的时候,可能需要对象实现Comparable接口,或者自己实现一个Comparator,

          -

          比如这样子

          -

          我的对象是Entity

          -
          public class Entity {
          -
          -    private Long id;
          -
          -    private Long sortValue;
          -
          -    public Long getId() {
          -        return id;
          -    }
          -
          -    public void setId(Long id) {
          -        this.id = id;
          +    Apollo 的 value 注解是怎么自动更新的
          +    /2020/11/01/Apollo-%E7%9A%84-value-%E6%B3%A8%E8%A7%A3%E6%98%AF%E6%80%8E%E4%B9%88%E8%87%AA%E5%8A%A8%E6%9B%B4%E6%96%B0%E7%9A%84/
          +    在前司和目前公司,用的配置中心都是使用的 Apollo,经过了业界验证,比较强大的配置管理系统,特别是在0.10 后开始支持对使用 value 注解的配置值进行自动更新,今天刚好有个同学问到我,就顺便写篇文章记录下,其实也是借助于 spring 强大的 bean 生命周期管理,可以实现BeanPostProcessor接口,使用postProcessBeforeInitialization方法,来对bean 内部的属性和方法进行判断,是否有 value 注解,如果有就是将它注册到一个 map 中,可以看到这个方法com.ctrip.framework.apollo.spring.annotation.SpringValueProcessor#processField

          +
          @Override
          +  protected void processField(Object bean, String beanName, Field field) {
          +    // register @Value on field
          +    Value value = field.getAnnotation(Value.class);
          +    if (value == null) {
          +      return;
               }
          +    Set<String> keys = placeholderHelper.extractPlaceholderKeys(value.value());
           
          -    public Long getSortValue() {
          -        return sortValue;
          +    if (keys.isEmpty()) {
          +      return;
               }
           
          -    public void setSortValue(Long sortValue) {
          -        this.sortValue = sortValue;
          +    for (String key : keys) {
          +      SpringValue springValue = new SpringValue(key, value.value(), bean, beanName, field, false);
          +      springValueRegistry.register(beanFactory, key, springValue);
          +      logger.debug("Monitoring {}", springValue);
               }
          -}
          + }
          +

          然后我们看下这个springValueRegistry是啥玩意

          +
          public class SpringValueRegistry {
          +  private static final long CLEAN_INTERVAL_IN_SECONDS = 5;
          +  private final Map<BeanFactory, Multimap<String, SpringValue>> registry = Maps.newConcurrentMap();
          +  private final AtomicBoolean initialized = new AtomicBoolean(false);
          +  private final Object LOCK = new Object();
           
          -

          Comparator

          -
          public class MyComparator implements Comparator {
          -    @Override
          -    public int compare(Object o1, Object o2) {
          -        Entity e1 = (Entity) o1;
          -        Entity e2 = (Entity) o2;
          -        if (e1.getSortValue() < e2.getSortValue()) {
          -            return -1;
          -        } else if (e1.getSortValue().equals(e2.getSortValue())) {
          -            return 0;
          -        } else {
          -            return 1;
          +  public void register(BeanFactory beanFactory, String key, SpringValue springValue) {
          +    if (!registry.containsKey(beanFactory)) {
          +      synchronized (LOCK) {
          +        if (!registry.containsKey(beanFactory)) {
          +          registry.put(beanFactory, LinkedListMultimap.<String, SpringValue>create());
                   }
          +      }
               }
          -}
          -

          比较代码

          -
          private static MyComparator myComparator = new MyComparator();
          +    registry.get(beanFactory).put(key, springValue);
           
          -    public static void main(String[] args) {
          -        List<Entity> list = new ArrayList<Entity>();
          -        Entity e1 = new Entity();
          -        e1.setId(1L);
          +    // lazy initialize
          +    if (initialized.compareAndSet(false, true)) {
          +      initialize();
          +    }
          +  }
          +

          这类其实就是个 map 来存放 springvalue,然后有com.ctrip.framework.apollo.spring.property.AutoUpdateConfigChangeListener来监听更新操作,当有变更时

          +
          @Override
          + public void onChange(ConfigChangeEvent changeEvent) {
          +   Set<String> keys = changeEvent.changedKeys();
          +   if (CollectionUtils.isEmpty(keys)) {
          +     return;
          +   }
          +   for (String key : keys) {
          +     // 1. check whether the changed key is relevant
          +     Collection<SpringValue> targetValues = springValueRegistry.get(beanFactory, key);
          +     if (targetValues == null || targetValues.isEmpty()) {
          +       continue;
          +     }
          +
          +     // 2. check whether the value is really changed or not (since spring property sources have hierarchies)
          +     // 这里其实有一点比较绕,是因为 Apollo 里的 namespace 划分,会出现 key 相同,但是 namespace 不同的情况,所以会有个优先级存在,所以需要去校验 environment 里面的是否已经更新,如果未更新则表示不需要更新
          +     if (!shouldTriggerAutoUpdate(changeEvent, key)) {
          +       continue;
          +     }
          +
          +     // 3. update the value
          +     for (SpringValue val : targetValues) {
          +       updateSpringValue(val);
          +     }
          +   }
          + }
          +

          其实原理很简单,就是得了解知道下

          +]]> + + Java + Apollo + value + + + Java + Apollo + value + 注解 + environment + + + + Comparator使用小记 + /2020/04/05/Comparator%E4%BD%BF%E7%94%A8%E5%B0%8F%E8%AE%B0/ + 在Java8的stream之前,将对象进行排序的时候,可能需要对象实现Comparable接口,或者自己实现一个Comparator,

          +

          比如这样子

          +

          我的对象是Entity

          +
          public class Entity {
          +
          +    private Long id;
          +
          +    private Long sortValue;
          +
          +    public Long getId() {
          +        return id;
          +    }
          +
          +    public void setId(Long id) {
          +        this.id = id;
          +    }
          +
          +    public Long getSortValue() {
          +        return sortValue;
          +    }
          +
          +    public void setSortValue(Long sortValue) {
          +        this.sortValue = sortValue;
          +    }
          +}
          + +

          Comparator

          +
          public class MyComparator implements Comparator {
          +    @Override
          +    public int compare(Object o1, Object o2) {
          +        Entity e1 = (Entity) o1;
          +        Entity e2 = (Entity) o2;
          +        if (e1.getSortValue() < e2.getSortValue()) {
          +            return -1;
          +        } else if (e1.getSortValue().equals(e2.getSortValue())) {
          +            return 0;
          +        } else {
          +            return 1;
          +        }
          +    }
          +}
          + +

          比较代码

          +
          private static MyComparator myComparator = new MyComparator();
          +
          +    public static void main(String[] args) {
          +        List<Entity> list = new ArrayList<Entity>();
          +        Entity e1 = new Entity();
          +        e1.setId(1L);
                   e1.setSortValue(1L);
                   list.add(e1);
                   Entity e2 = new Entity();
          @@ -1314,6 +1314,134 @@ Node *clone(Node *graph) {
                   nullsfirst
                 
             
          +  
          +    Disruptor 系列一
          +    /2022/02/13/Disruptor-%E7%B3%BB%E5%88%97%E4%B8%80/
          +    很久之前就听说过这个框架,不过之前有点跟消息队列混起来,这个也是种队列,但不是跟 rocketmq,nsq 那种一样的,而是在进程内部提供队列服务的,偏向于取代ArrayBlockingQueue,因为这个阻塞队列是使用了锁来控制阻塞,关于并发其实有一些通用的最佳实践,就是用锁,即使是 JDK 提供的锁,也是比较耗资源的,当然这是跟不加锁的对比,同样是锁,JDK 的实现还是性能比较优秀的。常见的阻塞队列中例如 ArrayBlockingQueueLinkedBlockingQueue 都有锁的身影的存在,区别在于 ArrayBlockingQueue 是一把锁,后者是两把锁,不过重点不在几把锁,这里其实是两个问题,一个是所谓的 lock free, 对于一个单生产者的 disruptor 来说,因为写入是只有一个线程的,是可以不用加锁,多生产者的时候使用的是 cas 来获取对应的写入坑位,另一个是解决“伪共享”问题,后面可以详细点分析,先介绍下使用
          首先是数据源

          +
          public class LongEvent {
          +    private long value;
          +
          +    public void set(long value) {
          +        this.value = value;
          +    }
          +
          +    public long getValue() {
          +        return value;
          +    }
          +
          +    public void setValue(long value) {
          +        this.value = value;
          +    }
          +}
          +

          事件生产

          +
          public class LongEventFactory implements EventFactory<LongEvent>
          +{
          +    public LongEvent newInstance()
          +    {
          +        return new LongEvent();
          +    }
          +}
          +

          事件处理器

          +
          public class LongEventHandler implements EventHandler<LongEvent> {
          +
          +    // event 事件,
          +    // sequence 当前的序列 
          +    // 是否当前批次最后一个数据
          +    public void onEvent(LongEvent event, long sequence, boolean endOfBatch)
          +    {
          +        String str = String.format("long event : %s l:%s b:%s", event.getValue(), sequence, endOfBatch);
          +        System.out.println(str);
          +    }
          +}
          +
          +

          主方法代码

          +
          package disruptor;
          +
          +import com.lmax.disruptor.RingBuffer;
          +import com.lmax.disruptor.dsl.Disruptor;
          +import com.lmax.disruptor.util.DaemonThreadFactory;
          +
          +import java.nio.ByteBuffer;
          +
          +public class LongEventMain
          +{
          +    public static void main(String[] args) throws Exception
          +    {
          +        // 这个需要是 2 的幂次,这样在定位的时候只需要位移操作,也能减少各种计算操作
          +        int bufferSize = 1024; 
          +
          +        Disruptor<LongEvent> disruptor = 
          +                new Disruptor<>(LongEvent::new, bufferSize, DaemonThreadFactory.INSTANCE);
          +
          +        // 类似于注册处理器
          +        disruptor.handleEventsWith(new LongEventHandler());
          +        // 或者直接用 lambda
          +        disruptor.handleEventsWith((event, sequence, endOfBatch) ->
          +                System.out.println("Event: " + event));
          +        // 启动我们的 disruptor
          +        disruptor.start(); 
          +
          +
          +        RingBuffer<LongEvent> ringBuffer = disruptor.getRingBuffer(); 
          +        ByteBuffer bb = ByteBuffer.allocate(8);
          +        for (long l = 0; true; l++)
          +        {
          +            bb.putLong(0, l);
          +            // 生产事件
          +            ringBuffer.publishEvent((event, sequence, buffer) -> event.set(buffer.getLong(0)), bb);
          +            Thread.sleep(1000);
          +        }
          +    }
          +}
          +

          运行下可以看到运行结果

          这里其实就只是最简单的使用,生产者只有一个,然后也不是批量的。

          +]]>
          + + Java + + + Java + Disruptor + +
          + + Disruptor 系列二 + /2022/02/27/Disruptor-%E7%B3%BB%E5%88%97%E4%BA%8C/ + 这里开始慢慢深入的讲一下 disruptor,首先是 lock free , 相比于前面介绍的两个阻塞队列,
          disruptor 本身是不直接使用锁的,因为本身的设计是单个线程去生产,通过 cas 来维护头指针,
          不直接维护尾指针,这样就减少了锁的使用,提升了性能;第二个是这次介绍的重点,
          减少 false sharing 的情况,也就是常说的 伪共享 问题,那么什么叫 伪共享 呢,
          这里要扯到一些 cpu 缓存的知识,

          譬如我在用的这个笔记本

          这里就可能看到 L2 Cache 就是针对每个核的

          这里可以看到现代 CPU 的结构里,分为三级缓存,越靠近 cpu 的速度越快,存储容量越小,
          而 L1 跟 L2 是 CPU 核专属的每个核都有自己的 L1 和 L2 的,其中 L1 还分为数据和指令,
          像我上面的图中显示的 L1 Cache 只有 64KB 大小,其中数据 32KB,指令 32KB,
          而 L2 则有 256KB,L3 有 4MB,其中的 Line Size 是我们这里比较重要的一个值,
          CPU 其实会就近地从 Cache 中读取数据,碰到 Cache Miss 就再往下一级 Cache 读取,
          每次读取是按照缓存行 Cache Line 读取,并且也遵循了“就近原则”,
          也就是相近的数据有可能也会马上被读取,所以以行的形式读取,然而这也造成了 false sharing
          因为类似于 ArrayBlockingQueue,需要有 takeIndex , putIndex , count , 因为在同一个类中,
          很有可能存在于同一个 Cache Line 中,但是这几个值会被不同的线程修改,
          导致从 Cache 取出来以后立马就会被失效,所谓的就近原则也就没用了,
          因为需要反复地标记 dirty 脏位,然后把 Cache 刷掉,就造成了false sharing这种情况
          而在 disruptor 中则使用了填充的方式,让我的头指针能够不产生false sharing

          +
          class LhsPadding
          +{
          +    protected long p1, p2, p3, p4, p5, p6, p7;
          +}
          +
          +class Value extends LhsPadding
          +{
          +    protected volatile long value;
          +}
          +
          +class RhsPadding extends Value
          +{
          +    protected long p9, p10, p11, p12, p13, p14, p15;
          +}
          +
          +/**
          + * <p>Concurrent sequence class used for tracking the progress of
          + * the ring buffer and event processors.  Support a number
          + * of concurrent operations including CAS and order writes.
          + *
          + * <p>Also attempts to be more efficient with regards to false
          + * sharing by adding padding around the volatile field.
          + */
          +public class Sequence extends RhsPadding
          +{
          +

          通过代码可以看到,sequence 中其实真正有意义的是 value 字段,因为需要在多线程环境下可见也
          使用了volatile 关键字,而 LhsPaddingRhsPadding 分别在value 前后填充了各
          7 个 long 型的变量,long 型的变量在 Java 中是占用 8 bytes,这样就相当于不管怎么样,
          value 都会单独使用一个缓存行,使得其不会产生 false sharing 的问题。

          +]]>
          + + Java + + + Java + Disruptor + +
          Filter, Interceptor, Aop, 啥, 啥, 啥? 这些都是啥? /2020/08/22/Filter-Intercepter-Aop-%E5%95%A5-%E5%95%A5-%E5%95%A5-%E8%BF%99%E4%BA%9B%E9%83%BD%E6%98%AF%E5%95%A5/ @@ -1865,226 +1993,26 @@ Node *clone(Node *graph) { - Disruptor 系列二 - /2022/02/27/Disruptor-%E7%B3%BB%E5%88%97%E4%BA%8C/ - 这里开始慢慢深入的讲一下 disruptor,首先是 lock free , 相比于前面介绍的两个阻塞队列,
          disruptor 本身是不直接使用锁的,因为本身的设计是单个线程去生产,通过 cas 来维护头指针,
          不直接维护尾指针,这样就减少了锁的使用,提升了性能;第二个是这次介绍的重点,
          减少 false sharing 的情况,也就是常说的 伪共享 问题,那么什么叫 伪共享 呢,
          这里要扯到一些 cpu 缓存的知识,

          譬如我在用的这个笔记本

          这里就可能看到 L2 Cache 就是针对每个核的

          这里可以看到现代 CPU 的结构里,分为三级缓存,越靠近 cpu 的速度越快,存储容量越小,
          而 L1 跟 L2 是 CPU 核专属的每个核都有自己的 L1 和 L2 的,其中 L1 还分为数据和指令,
          像我上面的图中显示的 L1 Cache 只有 64KB 大小,其中数据 32KB,指令 32KB,
          而 L2 则有 256KB,L3 有 4MB,其中的 Line Size 是我们这里比较重要的一个值,
          CPU 其实会就近地从 Cache 中读取数据,碰到 Cache Miss 就再往下一级 Cache 读取,
          每次读取是按照缓存行 Cache Line 读取,并且也遵循了“就近原则”,
          也就是相近的数据有可能也会马上被读取,所以以行的形式读取,然而这也造成了 false sharing
          因为类似于 ArrayBlockingQueue,需要有 takeIndex , putIndex , count , 因为在同一个类中,
          很有可能存在于同一个 Cache Line 中,但是这几个值会被不同的线程修改,
          导致从 Cache 取出来以后立马就会被失效,所谓的就近原则也就没用了,
          因为需要反复地标记 dirty 脏位,然后把 Cache 刷掉,就造成了false sharing这种情况
          而在 disruptor 中则使用了填充的方式,让我的头指针能够不产生false sharing

          -
          class LhsPadding
          -{
          -    protected long p1, p2, p3, p4, p5, p6, p7;
          -}
          +    JVM源码分析之G1垃圾收集器分析一
          +    /2019/12/07/JVM-G1-Part-1/
          +    对 Java 的 gc 实现比较感兴趣,原先一般都是看周志明的书,但其实并没有讲具体的 gc 源码,而是把整个思路和流程讲解了一下
          特别是 G1 的具体实现
          一般对 G1 的理解其实就是把原先整块的新生代老年代分成了以 region 为单位的小块内存,简而言之,就是原先对新生代老年代的收集会涉及到整个代的堆内存空间,而G1 把它变成了更细致的小块内存
          这带来了一个很明显的好处和一个很明显的坏处,好处是内存收集可以更灵活,耗时会变短,但整个收集的处理复杂度就变高了
          目前看了一点点关于 G1 收集的预期时间相关的代码

          +
          HeapWord* G1CollectedHeap::do_collection_pause(size_t word_size,
          +                                               uint gc_count_before,
          +                                               bool* succeeded,
          +                                               GCCause::Cause gc_cause) {
          +  assert_heap_not_locked_and_not_at_safepoint();
          +  VM_G1CollectForAllocation op(word_size,
          +                               gc_count_before,
          +                               gc_cause,
          +                               false, /* should_initiate_conc_mark */
          +                               g1_policy()->max_pause_time_ms());
          +  VMThread::execute(&op);
           
          -class Value extends LhsPadding
          -{
          -    protected volatile long value;
          -}
          -
          -class RhsPadding extends Value
          -{
          -    protected long p9, p10, p11, p12, p13, p14, p15;
          -}
          -
          -/**
          - * <p>Concurrent sequence class used for tracking the progress of
          - * the ring buffer and event processors.  Support a number
          - * of concurrent operations including CAS and order writes.
          - *
          - * <p>Also attempts to be more efficient with regards to false
          - * sharing by adding padding around the volatile field.
          - */
          -public class Sequence extends RhsPadding
          -{
          -

          通过代码可以看到,sequence 中其实真正有意义的是 value 字段,因为需要在多线程环境下可见也
          使用了volatile 关键字,而 LhsPaddingRhsPadding 分别在value 前后填充了各
          7 个 long 型的变量,long 型的变量在 Java 中是占用 8 bytes,这样就相当于不管怎么样,
          value 都会单独使用一个缓存行,使得其不会产生 false sharing 的问题。

          -]]>
          - - Java - - - Java - Disruptor - - - - Disruptor 系列一 - /2022/02/13/Disruptor-%E7%B3%BB%E5%88%97%E4%B8%80/ - 很久之前就听说过这个框架,不过之前有点跟消息队列混起来,这个也是种队列,但不是跟 rocketmq,nsq 那种一样的,而是在进程内部提供队列服务的,偏向于取代ArrayBlockingQueue,因为这个阻塞队列是使用了锁来控制阻塞,关于并发其实有一些通用的最佳实践,就是用锁,即使是 JDK 提供的锁,也是比较耗资源的,当然这是跟不加锁的对比,同样是锁,JDK 的实现还是性能比较优秀的。常见的阻塞队列中例如 ArrayBlockingQueueLinkedBlockingQueue 都有锁的身影的存在,区别在于 ArrayBlockingQueue 是一把锁,后者是两把锁,不过重点不在几把锁,这里其实是两个问题,一个是所谓的 lock free, 对于一个单生产者的 disruptor 来说,因为写入是只有一个线程的,是可以不用加锁,多生产者的时候使用的是 cas 来获取对应的写入坑位,另一个是解决“伪共享”问题,后面可以详细点分析,先介绍下使用
          首先是数据源

          -
          public class LongEvent {
          -    private long value;
          -
          -    public void set(long value) {
          -        this.value = value;
          -    }
          -
          -    public long getValue() {
          -        return value;
          -    }
          -
          -    public void setValue(long value) {
          -        this.value = value;
          -    }
          -}
          -

          事件生产

          -
          public class LongEventFactory implements EventFactory<LongEvent>
          -{
          -    public LongEvent newInstance()
          -    {
          -        return new LongEvent();
          -    }
          -}
          -

          事件处理器

          -
          public class LongEventHandler implements EventHandler<LongEvent> {
          -
          -    // event 事件,
          -    // sequence 当前的序列 
          -    // 是否当前批次最后一个数据
          -    public void onEvent(LongEvent event, long sequence, boolean endOfBatch)
          -    {
          -        String str = String.format("long event : %s l:%s b:%s", event.getValue(), sequence, endOfBatch);
          -        System.out.println(str);
          -    }
          -}
          -
          -

          主方法代码

          -
          package disruptor;
          -
          -import com.lmax.disruptor.RingBuffer;
          -import com.lmax.disruptor.dsl.Disruptor;
          -import com.lmax.disruptor.util.DaemonThreadFactory;
          -
          -import java.nio.ByteBuffer;
          -
          -public class LongEventMain
          -{
          -    public static void main(String[] args) throws Exception
          -    {
          -        // 这个需要是 2 的幂次,这样在定位的时候只需要位移操作,也能减少各种计算操作
          -        int bufferSize = 1024; 
          -
          -        Disruptor<LongEvent> disruptor = 
          -                new Disruptor<>(LongEvent::new, bufferSize, DaemonThreadFactory.INSTANCE);
          -
          -        // 类似于注册处理器
          -        disruptor.handleEventsWith(new LongEventHandler());
          -        // 或者直接用 lambda
          -        disruptor.handleEventsWith((event, sequence, endOfBatch) ->
          -                System.out.println("Event: " + event));
          -        // 启动我们的 disruptor
          -        disruptor.start(); 
          -
          -
          -        RingBuffer<LongEvent> ringBuffer = disruptor.getRingBuffer(); 
          -        ByteBuffer bb = ByteBuffer.allocate(8);
          -        for (long l = 0; true; l++)
          -        {
          -            bb.putLong(0, l);
          -            // 生产事件
          -            ringBuffer.publishEvent((event, sequence, buffer) -> event.set(buffer.getLong(0)), bb);
          -            Thread.sleep(1000);
          -        }
          -    }
          -}
          -

          运行下可以看到运行结果

          这里其实就只是最简单的使用,生产者只有一个,然后也不是批量的。

          -]]>
          - - Java - - - Java - Disruptor - -
          - - Leetcode 021 合并两个有序链表 ( Merge Two Sorted Lists ) 题解分析 - /2021/10/07/Leetcode-021-%E5%90%88%E5%B9%B6%E4%B8%A4%E4%B8%AA%E6%9C%89%E5%BA%8F%E9%93%BE%E8%A1%A8-Merge-Two-Sorted-Lists-%E9%A2%98%E8%A7%A3%E5%88%86%E6%9E%90/ - 题目介绍

          Merge two sorted linked lists and return it as a sorted list. The list should be made by splicing together the nodes of the first two lists.

          -

          将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

          -

          示例 1

          -
          -

          输入:l1 = [1,2,4], l2 = [1,3,4]
          输出:[1,1,2,3,4,4]

          -
          -

          示例 2

          -

          输入: l1 = [], l2 = []
          输出: []

          -
          -

          示例 3

          -

          输入: l1 = [], l2 = [0]
          输出: [0]

          -
          -

          简要分析

          这题是 Easy 的,看着也挺简单,两个链表进行合并,就是比较下大小,可能将就点的话最好就在两个链表中原地合并

          -

          题解代码

          public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
          -        // 下面两个if判断了入参的边界,如果其一为null,直接返回另一个就可以了
          -        if (l1 == null) {
          -            return l2;
          -        }
          -        if (l2 == null) {
          -            return l1;
          -        }
          -        // new 一个合并后的头结点
          -        ListNode merged = new ListNode();
          -        // 这个是当前节点
          -        ListNode current = merged;
          -        // 一开始给这个while加了l1和l2不全为null的条件,后面想了下不需要
          -        // 因为内部前两个if就是跳出条件
          -        while (true) {
          -            if (l1 == null) {
          -                // 这里其实跟开头类似,只不过这里需要将l2剩余部分接到merged链表后面
          -                // 所以不能是直接current = l2,这样就是把后面的直接丢了
          -                current.val = l2.val;
          -                current.next = l2.next;
          -                break;
          -            }
          -            if (l2 == null) {
          -                current.val = l1.val;
          -                current.next = l1.next;
          -                break;
          -            }
          -            // 这里是两个链表都不为空的时候,就比较下大小
          -            if (l1.val < l2.val) {
          -                current.val = l1.val;
          -                l1 = l1.next;
          -            } else {
          -                current.val = l2.val;
          -                l2 = l2.next;
          -            }
          -            // 这里是new个新的,其实也可以放在循环头上
          -            current.next = new ListNode();
          -            current = current.next;
          -        }
          -        current = null;
          -        // 返回这个头结点
          -        return merged;
          -    }
          - -

          结果

          -]]>
          - - Java - leetcode - - - leetcode - java - 题解 - -
          - - JVM源码分析之G1垃圾收集器分析一 - /2019/12/07/JVM-G1-Part-1/ - 对 Java 的 gc 实现比较感兴趣,原先一般都是看周志明的书,但其实并没有讲具体的 gc 源码,而是把整个思路和流程讲解了一下
          特别是 G1 的具体实现
          一般对 G1 的理解其实就是把原先整块的新生代老年代分成了以 region 为单位的小块内存,简而言之,就是原先对新生代老年代的收集会涉及到整个代的堆内存空间,而G1 把它变成了更细致的小块内存
          这带来了一个很明显的好处和一个很明显的坏处,好处是内存收集可以更灵活,耗时会变短,但整个收集的处理复杂度就变高了
          目前看了一点点关于 G1 收集的预期时间相关的代码

          -
          HeapWord* G1CollectedHeap::do_collection_pause(size_t word_size,
          -                                               uint gc_count_before,
          -                                               bool* succeeded,
          -                                               GCCause::Cause gc_cause) {
          -  assert_heap_not_locked_and_not_at_safepoint();
          -  VM_G1CollectForAllocation op(word_size,
          -                               gc_count_before,
          -                               gc_cause,
          -                               false, /* should_initiate_conc_mark */
          -                               g1_policy()->max_pause_time_ms());
          -  VMThread::execute(&op);
          -
          -  HeapWord* result = op.result();
          -  bool ret_succeeded = op.prologue_succeeded() && op.pause_succeeded();
          -  assert(result == NULL || ret_succeeded,
          -         "the result should be NULL if the VM did not succeed");
          -  *succeeded = ret_succeeded;
          +  HeapWord* result = op.result();
          +  bool ret_succeeded = op.prologue_succeeded() && op.pause_succeeded();
          +  assert(result == NULL || ret_succeeded,
          +         "the result should be NULL if the VM did not succeed");
          +  *succeeded = ret_succeeded;
           
             assert_heap_not_locked();
             return result;
          @@ -2671,35 +2599,107 @@ Node *clone(Node *graph) {
                 
             
             
          -    Leetcode 028 实现 strStr() ( Implement strStr() ) 题解分析
          -    /2021/10/31/Leetcode-028-%E5%AE%9E%E7%8E%B0-strStr-Implement-strStr-%E9%A2%98%E8%A7%A3%E5%88%86%E6%9E%90/
          -    题目介绍

          Implement strStr().

          -

          Return the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack.

          -

          Clarification:

          What should we return when needle is an empty string? This is a great question to ask during an interview.

          -

          For the purpose of this problem, we will return 0 when needle is an empty string. This is consistent to C’s strstr() and Java’s indexOf().

          -

          示例

          Example 1:

          -
          Input: haystack = "hello", needle = "ll"
          -Output: 2
          -

          Example 2:

          -
          Input: haystack = "aaaaa", needle = "bba"
          -Output: -1
          -

          Example 3:

          -
          Input: haystack = "", needle = ""
          -Output: 0
          - -

          题解

          字符串比较其实是写代码里永恒的主题,底层的编译器等处理肯定需要字符串对比,像 kmp 算法也是很厉害

          -

          code

          public int strStr(String haystack, String needle) {
          -        // 如果两个字符串都为空,返回 -1
          -        if (haystack == null || needle == null) {
          -            return -1;
          +    Leetcode 021 合并两个有序链表 ( Merge Two Sorted Lists ) 题解分析
          +    /2021/10/07/Leetcode-021-%E5%90%88%E5%B9%B6%E4%B8%A4%E4%B8%AA%E6%9C%89%E5%BA%8F%E9%93%BE%E8%A1%A8-Merge-Two-Sorted-Lists-%E9%A2%98%E8%A7%A3%E5%88%86%E6%9E%90/
          +    题目介绍

          Merge two sorted linked lists and return it as a sorted list. The list should be made by splicing together the nodes of the first two lists.

          +

          将两个升序链表合并为一个新的 升序 链表并返回。新链表是通过拼接给定的两个链表的所有节点组成的。

          +

          示例 1

          +
          +

          输入:l1 = [1,2,4], l2 = [1,3,4]
          输出:[1,1,2,3,4,4]

          +
          +

          示例 2

          +

          输入: l1 = [], l2 = []
          输出: []

          +
          +

          示例 3

          +

          输入: l1 = [], l2 = [0]
          输出: [0]

          +
          +

          简要分析

          这题是 Easy 的,看着也挺简单,两个链表进行合并,就是比较下大小,可能将就点的话最好就在两个链表中原地合并

          +

          题解代码

          public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
          +        // 下面两个if判断了入参的边界,如果其一为null,直接返回另一个就可以了
          +        if (l1 == null) {
          +            return l2;
                   }
          -        // 如果 haystack 长度小于 needle 长度,返回 -1
          -        if (haystack.length() < needle.length()) {
          -            return -1;
          +        if (l2 == null) {
          +            return l1;
                   }
          -        // 如果 needle 为空字符串,返回 0
          -        if (needle.equals("")) {
          -            return 0;
          +        // new 一个合并后的头结点
          +        ListNode merged = new ListNode();
          +        // 这个是当前节点
          +        ListNode current = merged;
          +        // 一开始给这个while加了l1和l2不全为null的条件,后面想了下不需要
          +        // 因为内部前两个if就是跳出条件
          +        while (true) {
          +            if (l1 == null) {
          +                // 这里其实跟开头类似,只不过这里需要将l2剩余部分接到merged链表后面
          +                // 所以不能是直接current = l2,这样就是把后面的直接丢了
          +                current.val = l2.val;
          +                current.next = l2.next;
          +                break;
          +            }
          +            if (l2 == null) {
          +                current.val = l1.val;
          +                current.next = l1.next;
          +                break;
          +            }
          +            // 这里是两个链表都不为空的时候,就比较下大小
          +            if (l1.val < l2.val) {
          +                current.val = l1.val;
          +                l1 = l1.next;
          +            } else {
          +                current.val = l2.val;
          +                l2 = l2.next;
          +            }
          +            // 这里是new个新的,其实也可以放在循环头上
          +            current.next = new ListNode();
          +            current = current.next;
          +        }
          +        current = null;
          +        // 返回这个头结点
          +        return merged;
          +    }
          + +

          结果

          +]]>
          + + Java + leetcode + + + leetcode + java + 题解 + + + + Leetcode 028 实现 strStr() ( Implement strStr() ) 题解分析 + /2021/10/31/Leetcode-028-%E5%AE%9E%E7%8E%B0-strStr-Implement-strStr-%E9%A2%98%E8%A7%A3%E5%88%86%E6%9E%90/ + 题目介绍

          Implement strStr().

          +

          Return the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack.

          +

          Clarification:

          What should we return when needle is an empty string? This is a great question to ask during an interview.

          +

          For the purpose of this problem, we will return 0 when needle is an empty string. This is consistent to C’s strstr() and Java’s indexOf().

          +

          示例

          Example 1:

          +
          Input: haystack = "hello", needle = "ll"
          +Output: 2
          +

          Example 2:

          +
          Input: haystack = "aaaaa", needle = "bba"
          +Output: -1
          +

          Example 3:

          +
          Input: haystack = "", needle = ""
          +Output: 0
          + +

          题解

          字符串比较其实是写代码里永恒的主题,底层的编译器等处理肯定需要字符串对比,像 kmp 算法也是很厉害

          +

          code

          public int strStr(String haystack, String needle) {
          +        // 如果两个字符串都为空,返回 -1
          +        if (haystack == null || needle == null) {
          +            return -1;
          +        }
          +        // 如果 haystack 长度小于 needle 长度,返回 -1
          +        if (haystack.length() < needle.length()) {
          +            return -1;
          +        }
          +        // 如果 needle 为空字符串,返回 0
          +        if (needle.equals("")) {
          +            return 0;
                   }
                   // 如果两者相等,返回 0
                   if (haystack.equals(needle)) {
          @@ -3394,72 +3394,6 @@ Output: 0
          -

          用个存储过程来插入数据

          -
          
          -delimiter $	#以delimiter来标记用$表示存储过程结束
          -create procedure nullIndex1()
          -begin
          -declare i int;	
          -declare j int;	
          -set i=1;
          -set j=1;
          -while(i<=100) do	
          -	while(j<=100) do	
          -		IF (i % 3 = 0) THEN
          -	     INSERT INTO null_index_t ( `null_key`, `null_key1`, `null_key2` ) VALUES (null , LEFT(MD5(RAND()), 8), LEFT(MD5(RAND()), 8));
          -    ELSEIF (i % 3 = 1) THEN
          -			 INSERT INTO null_index_t ( `null_key`, `null_key1`, `null_key2` ) VALUES (LEFT(MD5(RAND()), 8), NULL, LEFT(MD5(RAND()), 8));
          -	  ELSE
          -			 INSERT INTO null_index_t ( `null_key`, `null_key1`, `null_key2` ) VALUES (LEFT(MD5(RAND()), 8), LEFT(MD5(RAND()), 8), NULL);
          -    END IF;
          -		set j=j+1;
          -	end while;
          -	set i=i+1;
          -	set j=1;	
          -end while;
          -end 
          -$
          -call nullIndex1();
          -

          然后看下我们的 is null 查询

          -
          EXPLAIN select * from null_index_t WHERE null_key is null;
          -


          再来看看另一个

          -
          EXPLAIN select * from null_index_t WHERE null_key is not null;
          -


          从这里能看出来啥呢,可以思考下

          -

          从上面可以发现,is null应该是用上了索引了,所以至少不是一刀切不能用,但是看着is not null好像不太行额
          我们在做一点小改动,把这个表里的数据改成 9100 条是 null,剩下 900 条是有值的,然后再执行下

          然后再来看看执行结果

          -
          EXPLAIN select * from null_index_t WHERE null_key is null;
          -

          -
          EXPLAIN select * from null_index_t WHERE null_key is not null;
          -


          是不是不一样了,这里再补充下我试验使用的 mysql 是 5.7 的,不保证在其他版本的一致性,
          其实可以看出随着数据量的变化,mysql 会不会使用索引是会变化的,不是说 is not null 一定会使用,也不是一定不会使用,而是优化器会根据查询成本做个预判,这个预判尽可能会减小查询成本,主要包括回表啥的,但是也不一定完全准确。

          -]]>
          - - Mysql - C - 索引 - Mysql - - - mysql - 索引 - is null - is not null - procedure - -
          - - 聊聊Java中的单例模式 - /2019/12/21/%E8%81%8A%E8%81%8AJava%E4%B8%AD%E7%9A%84%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F/ - 这是个 Java 面试的高频问题,我也遇到过,以往都是觉得这类题没意思,网上一搜一大堆,也不愿意记,其实说回来,主要还是没静下心来好好去理解,今天无意中看到一个课程,基本帮我把一些疑惑的点讲清楚了,首先单例是啥意思,这个其实是有范围一说,比如我起了个Spring Boot应用,在这个应用范围内,我的常规 bean 是单例的,意味着 getBean 的时候其实永远只会拿到那一个对象,那要怎么来写一个单例呢,首先就是传说中的饿汉模式,也是最简单的

          -

          饿汉模式

          public class Singleton1 {
          -    // 首先,将构造方法变成私有的
          -    private Singleton1() {};
          -    // 创建私有静态实例,这样第一次使用的时候就会进行创建
          -    private static Singleton instance = new Singleton1();
          -
          -    // 使用这个对象都是通过这个 getInstance 来获取
          -    public static Singleton1 getInstance() {
          -        return instance;
          -    }
          -    // 瞎写一个静态方法。这里想说的是,如果我们只是要调用 Singleton.getDate(...),
          -    // 本来是不想要生成 Singleton 实例的,不过没办法,已经生成了
          -    public static Date getDate(String mode) {return new Date();}
          -}
          -

          上面借鉴了一些代码,其实这是最基本,也不会错的方法,但是正如其中getDate方法里说的问题,有时候并没有想那这个对象,但是因为我调用了这个类的静态方法,导致对象已经生成了,可能这也是饿汉模式名字的来由,不管三七二十一给你生成个单例就完事了,不管有没有用,但是这种个人觉得也没啥大问题,如果是面试的话最好说出来它的缺点

          -

          饱汉模式

          public class Singleton2 {
          -    // 首先,也是先堵死 new Singleton() 这条路,将构造方法变成私有
          -    private Singleton2() {}
          -    // 和饿汉模式相比,这边不需要先实例化出来,注意这里的 volatile,它是必须的
          -    private static volatile Singleton2 instance = null;
          -
          -    private int m = 9;
          -
          -    public static Singleton getInstance() {
          -        if (instance == null) {
          -            // 加锁
          -            synchronized (Singleton2.class) {
          -                // 这一次判断也是必须的,不然会有并发问题
          -                if (instance == null) {
          -                    instance = new Singleton2();
          -                }
          -            }
          -        }
          -        return instance;
          -    }
          -}
          -

          这里容易错的有三点,理解了其实就比较好记了

          -

          第一点,为啥不在 getInstance 上整个代码块加 synchronized,这个其实比较容易理解,就是锁的力度太大,性能太差了,这点其实也要去理解,可以举个夸张的例子,比如我一个电商的服务,如果为了避免一个人的订单出现问题,是不是可以从请求入口就把他锁住,到请求结束释放,那么里面做的事情都有保障,然而这显然不可能,因为我们想要这种竞态条件抢占资源的时间尽量减少,防止其他线程等待。
          第二点,为啥synchronized之已经检查了 instance == null,还要在里面再检查一次,这个有个术语,叫 double check lock,但是为啥要这么做呢,其实很简单,想象当有两个线程,都过了第一步为空判断,这个时候只有一个线程能拿到这个锁,另一个线程就等待了,如果不再判断一次,那么第一个线程新建完对象释放锁之后,第二个线程又能拿到锁,再去创建一个对象。
          第三点,为啥要volatile关键字,原先对它的理解是它修饰的变量在 JMM 中能及时将变量值写到主存中,但是它还有个很重要的作用,就是防止指令重排序,instance = new Singleton();这行代码其实在底层是分成三条指令执行的,第一条是在堆上申请了一块内存放这个对象,但是对象的字段啥的都还是默认值,第二条是设置对象的值,比如上面的 m 是 9,然后第三条是将这个对象和虚拟机栈上的指针建立引用关联,那么如果我不用volatile关键字,这三条指令就有可能出现重排,比如变成了 1-3-2 这种顺序,当执行完第二步时,有个线程来访问这个对象了,先判断是不是空,发现不是空的,就拿去直接用了,是不是就出现问题了,所以这个volatile也是不可缺少的

          -

          嵌套类

          public class Singleton3 {
          -
          -    private Singleton3() {}
          -    // 主要是使用了 嵌套类可以访问外部类的静态属性和静态方法 的特性
          -    private static class Holder {
          -        private static Singleton3 instance = new Singleton3();
          -    }
          -    public static Singleton3 getInstance() {
          -        return Holder.instance;
          -    }
          -}
          -

          这个我个人感觉是饿汉模式的升级版,可以在调用getInstance的时候去实例化对象,也是比较推荐的

          -

          枚举单例

          public enum Singleton {
          -    INSTANCE;
          -    
          -    public void doSomething(){
          -        //todo doSomething
          -    }
          -}
          -

          枚举很特殊,它在类加载的时候会初始化里面的所有的实例,而且 JVM 保证了它们不会再被实例化,所以它天生就是单例的。

          + KEY `idx_1` (`null_key`) USING BTREE, + KEY `idx_2` (`null_key1`) USING BTREE, + KEY `idx_3` (`null_key2`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
          +

          用个存储过程来插入数据

          +
          
          +delimiter $	#以delimiter来标记用$表示存储过程结束
          +create procedure nullIndex1()
          +begin
          +declare i int;	
          +declare j int;	
          +set i=1;
          +set j=1;
          +while(i<=100) do	
          +	while(j<=100) do	
          +		IF (i % 3 = 0) THEN
          +	     INSERT INTO null_index_t ( `null_key`, `null_key1`, `null_key2` ) VALUES (null , LEFT(MD5(RAND()), 8), LEFT(MD5(RAND()), 8));
          +    ELSEIF (i % 3 = 1) THEN
          +			 INSERT INTO null_index_t ( `null_key`, `null_key1`, `null_key2` ) VALUES (LEFT(MD5(RAND()), 8), NULL, LEFT(MD5(RAND()), 8));
          +	  ELSE
          +			 INSERT INTO null_index_t ( `null_key`, `null_key1`, `null_key2` ) VALUES (LEFT(MD5(RAND()), 8), LEFT(MD5(RAND()), 8), NULL);
          +    END IF;
          +		set j=j+1;
          +	end while;
          +	set i=i+1;
          +	set j=1;	
          +end while;
          +end 
          +$
          +call nullIndex1();
          +

          然后看下我们的 is null 查询

          +
          EXPLAIN select * from null_index_t WHERE null_key is null;
          +


          再来看看另一个

          +
          EXPLAIN select * from null_index_t WHERE null_key is not null;
          +


          从这里能看出来啥呢,可以思考下

          +

          从上面可以发现,is null应该是用上了索引了,所以至少不是一刀切不能用,但是看着is not null好像不太行额
          我们在做一点小改动,把这个表里的数据改成 9100 条是 null,剩下 900 条是有值的,然后再执行下

          然后再来看看执行结果

          +
          EXPLAIN select * from null_index_t WHERE null_key is null;
          +

          +
          EXPLAIN select * from null_index_t WHERE null_key is not null;
          +


          是不是不一样了,这里再补充下我试验使用的 mysql 是 5.7 的,不保证在其他版本的一致性,
          其实可以看出随着数据量的变化,mysql 会不会使用索引是会变化的,不是说 is not null 一定会使用,也不是一定不会使用,而是优化器会根据查询成本做个预判,这个预判尽可能会减小查询成本,主要包括回表啥的,但是也不一定完全准确。

          ]]>
          - Java - Design Patterns - Singleton + Mysql + C + 索引 + Mysql - 设计模式 - Design Patterns - 单例 - Singleton + mysql + 索引 + is null + is not null + procedure + +
          + + 聊聊 redis 缓存的应用问题 + /2021/01/31/%E8%81%8A%E8%81%8A-redis-%E7%BC%93%E5%AD%98%E7%9A%84%E5%BA%94%E7%94%A8%E9%97%AE%E9%A2%98/ + 前面写过一系列的 redis 源码分析的,但是实际上很多的问题还是需要结合实际的使用,然后其实就避不开缓存使用的三个著名问题,穿透,击穿和雪崩,这三个概念也是有着千丝万缕的关系,

          +

          缓存穿透

          缓存穿透是指当数据库中本身就不存在这个数据的时候,使用一般的缓存策略时访问不到缓存后就访问数据库,但是因为数据库也没数据,所以如果不做任何策略优化的话,这类数据就每次都会访问一次数据库,对数据库压力也会比较大。

          +

          缓存击穿

          缓存击穿跟穿透比较类似的,都是访问缓存不在,然后去访问数据库,与穿透不一样的是击穿是在数据库中存在数据,但是可能由于第一次访问,或者缓存过期了,需要访问到数据库,这对于访问量小的情况其实算是个正常情况,但是随着请求量变高就会引发一些性能隐患。

          +

          缓存雪崩

          缓存雪崩就是击穿的大规模集群效应,当大量的缓存过期失效的时候,这些请求都是直接访问到数据库了,会对数据库造成很大的压力。

          +

          对于以上三种场景也有一些比较常见的解决方案,但也不能说是万无一失的,需要随着业务去寻找合适的方案

          +

          解决缓存穿透

          对于数据库中就没这个数据的时候,一种是可以对这个 key 设置下空值,即以一个特定的表示是数据库不存在的,这种情况需要合理地调整过期时间,当这个 key 在数据库中有数据了的话,也需要有策略去更新这个值,并且如果这类 key 非常多,这个方法就会不太合适,就可以使用第二种方法,就是布隆过滤器,bloom filter,前置一个布隆过滤器,当这个 key 在数据库不存在的话,先用布隆过滤器挡一道,如果不在的话就直接返回了,当然布隆过滤器不是绝对的准确的

          +

          解决缓存击穿

          当一个 key 的缓存过期了,如果大量请求过来访问这个 key,请求都会落在数据库里,这个时候就可以使用一些类似于互斥锁的方式去让一个线程去访问数据库,更新缓存,但是这里其实也有个问题,就是如果是热点 key 其实这种方式也比较危险,万一更新失败,或者更新操作的时候耗时比较久,就会有一大堆请求卡在那,这种情况可能需要有一些异步提前刷新缓存,可以结合具体场景选择方式

          +

          解决缓存雪崩

          雪崩的情况是指大批量的 key 都一起过期了,击穿的放大版,大批量的请求都打到数据库上了,一方面有可能直接缓存不可用了,就需要用集群化高可用的缓存服务,然后对于实际使用中也可以使用本地缓存结合 redis 缓存,去提高可用性,再配合一些限流措施,然后就是缓存使用过程总的过期时间最好能加一些随机值,防止在同一时间过期而导致雪崩,结合互斥锁防止大量请求打到数据库。

          +]]>
          + + Redis + 应用 + 缓存 + 缓存 + 穿透 + 击穿 + 雪崩 + + + Redis + 缓存穿透 + 缓存击穿 + 缓存雪崩 + 布隆过滤器 + bloom filter + 互斥锁
          @@ -13554,6 +13569,88 @@ $ AutoConfiguration + + 聊聊一次 brew update 引发的血案 + /2020/06/13/%E8%81%8A%E8%81%8A%E4%B8%80%E6%AC%A1-brew-update-%E5%BC%95%E5%8F%91%E7%9A%84%E8%A1%80%E6%A1%88/ + 熟悉我的人(谁熟悉你啊🙄)知道我以前写过 PHP,虽然现在在工作中没用到了,但是自己的一些小工具还是会用 PHP 来写,但是在 Mac 碰到了一个环境相关的问题,因为我也是个更新狂魔,用了 brew 之后因为 gfw 的原因,如果长时间不更新,有时候要装一个用它装一个软件的话,前置的更新耗时就会让人非常头大,所以我基本会隔天 update 一下,但是这样会带来一个很心烦的问题,就是像这样,因为我是要用一个固定版本的 PHP,如果一直升需要一直配扩展啥的也很麻烦,如果一直升级 PHP 到最新版可能会比较少碰到这个问题

          +
          dyld: Library not loaded: /usr/local/opt/icu4c/lib/libicui18n.64.dylib
          +

          这是什么鬼啊,然后我去这个目录下看了下,已经都是libicui18n.67.dylib了,而且它没有把原来的版本保留下来,首先这个是个叫 icu4c是啥玩意,谷歌了一下

          +
          +

          ICU4C是ICU在C/C++平台下的版本, ICU(International Component for Unicode)是基于”IBM公共许可证”的,与开源组织合作研究的, 用于支持软件国际化的开源项目。ICU4C提供了C/C++平台强大的国际化开发能力,软件开发者几乎可以使用ICU4C解决任何国际化的问题,根据各地的风俗和语言习惯,实现对数字、货币、时间、日期、和消息的格式化、解析,对字符串进行大小写转换、整理、搜索和排序等功能,必须一提的是,ICU4C提供了强大的BIDI算法,对阿拉伯语等BIDI语言提供了完善的支持。

          +
          +

          然后首先想到的解决方案就是能不能我使用brew install icu4c@64来重装下原来的版本,发现不行,并木有,之前的做法就只能是去网上把 64 的下载下来,然后放到这个目录,比较麻烦不智能,虽然没抱着希望在谷歌着,不过这次竟然给我找到了一个我认为非常 nice 的解决方案,因为是在 Stack Overflow 找到的,本着写给像我这样的小小白看的,那就稍微翻译一下
          第一步,我们到 brew的目录下

          +
          cd $(brew --prefix)/Homebrew/Library/Taps/homebrew/homebrew-core/Formula
          +

          这个可以理解为是 maven 的 pom 文件,不过有很多不同之处,使用ruby 写的,然后一个文件对应一个组件或者软件,那我们看下有个叫icu4c.rb的文件,
          第二步看看它的提交历史

          +
          git log --follow icu4c.rb
          +

          在 git log 的海洋中寻找,寻找它的(64版本)的身影

          第三步注意这三个红框,Stack Overflow 给出来的答案这一步是找到这个 commit id 直接切出一个新分支

          +
          git checkout -b icu4c-63 e7f0f10dc63b1dc1061d475f1a61d01b70ef2cb7
          +

          其实注意 commit id 旁边的红框,这个是有tag 的,可以直接

          +
          git checkout icu4c-64
          +

          PS: 因为我的问题是出在 64 的问题,Stack Overflow 回答的是 63 的,反正是一样的解决方法
          第四部,切回去之后我们就可以用 brew 提供的基于文件的安装命令来重新装上 64 版本

          +
          brew reinstall ./icu4c.rb
          +

          然后就是第五步,切换版本

          +
          brew switch icu4c 64.2
          +

          最后把分支切回来

          +
          git checkout master
          +

          是不是感觉很厉害的解决方法,大佬还提供了一个更牛的,直接写个 zsh 方法

          +
          # zsh
          +function hiicu64() {
          +  local last_dir=$(pwd)
          +
          +  cd $(brew --prefix)/Homebrew/Library/Taps/homebrew/homebrew-core/Formula
          +  git checkout icu4c-4
          +  brew reinstall ./icu4c.rb
          +  brew switch icu4c 64.2
          +  git checkout master
          +
          +  cd $last_dir
          +}
          +

          对应自己的版本改改版本号就可以了,非常好用。

          +]]>
          + + Mac + PHP + Homebrew + icu4c + + + Mac + PHP + Homebrew + icu4c + zsh + +
          + + 聊聊厦门旅游的好与不好 + /2021/04/11/%E8%81%8A%E8%81%8A%E5%8E%A6%E9%97%A8%E6%97%85%E6%B8%B8%E7%9A%84%E5%A5%BD%E4%B8%8E%E4%B8%8D%E5%A5%BD/ + 这几天去了趟厦门,原来几年前就想去了,本来都请好假了,后面因为一些事情没去成,这次刚好公司组织,就跟 LD 一起去了厦门,也不洋洋洒洒地写游记了,后面可能会有,今天先来总结下好的地方和比较坑的地方。
          这次主要去了中山路、鼓浪屿、曾厝(cuo)垵、植物园、灵玲马戏团,因为住的离环岛路比较近,还有幸现场看了下厦门马拉松,其中

          +

          中山路

          这里看上去是有点民国时期的建筑风格,部分像那种电视里的租界啥的,不过这次去的时候都在翻修,路一大半拦起来了,听导游说这里往里面走有个局口街,然后上次听前同事说厦门比较有名的就是沙茶面和海蛎煎,不出意料的不太爱吃,沙茶面比较普通,可能是没吃到正宗的,海蛎煎吃不惯,倒是有个大叔的沙茶里脊还不错,在局口街那,还有小哥在那拍,应该也算是个网红打卡点了,然后吃了个油条麻糍也还不错,总体如果是看建筑的话可能最近不是个好时间,个人也没这方面爱好,吃的话最好多打听打听沙茶面跟海蛎煎哪里正宗。如果不知道哪家好吃,也不爱看这类建筑的可以排个坑。

          +

          鼓浪屿

          鼓浪屿也是完全没啥概念,需要乘船过去,但是只要二十分钟,岛上没有机动车,基本都靠走,有几个比较有名的地方,菽庄花园,里面有钢琴博物馆,对这个感兴趣的可以去看看,旁边是沙滩还可以逛逛,然后有各种博物馆,风琴啥的,岛上最大的特色是巷子多,道听途说有三百多条小巷,还有几个网红打卡点,周杰伦晴天墙,还有个最美转角,都是挤满了人排队打卡拍照,不过如果不着急,慢慢悠悠逛逛还是不错的,比较推荐,推荐值☆☆

          +

          曾厝垵

          一直读不对这个字,都是叫:那个曾什么垵,愧对语文老师,这里到算是意外之喜,鼓浪屿回来已经挺累了,不过由于比较饿(什么原因后面说),并且离住的地方不远,就过去逛了逛,东西还蛮好吃的,芒果挺便宜,一大杯才十块,无骨鸡爪很贵,不是特别爱,臭豆腐不错的,也不算很贵,这里想起来,那边八婆婆的豆乳烧仙草还不错的,去中山路那会喝了,来曾厝垵也买了,奶茶爱好者可以试试,含糖量应该很高,不爱甜食或者减肥的同学慎重考虑好了再尝试,晚上那边从牌坊出来,沿着环岛路挺多夜宵店什么的,非常推荐,推荐值☆☆☆☆

          +

          植物园

          植物园还是挺名副其实的,有热带植物,沙漠多肉,因为赶时间逛得不多,热带雨林植物那太多人了,都是在那拍照,而且我指的拍照都是拍人照,本身就很小的路,各种十八线网红,或者普通游客在那摆 pose 拍照,挺无语的;沙漠多肉比较惊喜,好多比人高的仙人掌,一大片的仙人球,很可恶的是好多大仙人掌上都有人刻字,越来越体会到,我们社会人多了,什么样的都有,而且不少;还看了下百花厅,但没什么特别的,可能赶时间比较着急,没仔细看,比较推荐,推荐值☆☆☆

          +

          灵玲马戏团

          对这个其实比较排斥,主要是比较晚了,跑的有点远(我太懒了),一开始真的挺拉低体验感受的,上来个什么书法家,现场画马,卖画;不过后面的还算值回票价,主题是花木兰,空中动作应该很考验基本功,然后那些老外的飞轮还跳绳(不知道学名叫啥),动物那块不太忍心看,应该是吃了不少苦头,不过人都这样就往后点再心疼动物吧。

          +

          总结

          厦门是个非常适合干饭人的地方,吃饭的地方大部分是差不多一桌菜十个左右就完了,而且上来就一大碗饭,一瓶雪碧一瓶可乐,对于经常是家里跟亲戚吃饭都得十几二十个菜的乡下人来说,不太吃得惯这样的🤦‍♂️,当然很有可能是我们预算不足,点的差。但是有一点是我回杭州深有感触的,感觉杭州司机的素质真的是跟厦门的司机差了比较多,杭州除非公交车停了,否则人行道很难看到主动让人的,当然这里拿厦门这个旅游城市来对比也不是很公平,不过这也是体现城市现代化文明水平的一个维度吧。

          +]]>
          + + 生活 + 旅游 + + + 生活 + 杭州 + 旅游 + 厦门 + 中山路 + 局口街 + 鼓浪屿 + 曾厝垵 + 植物园 + 马戏团 + 沙茶面 + 海蛎煎 + +
          聊聊传说中的 ThreadLocal /2021/05/30/%E8%81%8A%E8%81%8A%E4%BC%A0%E8%AF%B4%E4%B8%AD%E7%9A%84-ThreadLocal/ @@ -13666,93 +13763,11 @@ $ Java - Java - ThreadLocal - 弱引用 - 内存泄漏 - WeakReference - - - - 聊聊一次 brew update 引发的血案 - /2020/06/13/%E8%81%8A%E8%81%8A%E4%B8%80%E6%AC%A1-brew-update-%E5%BC%95%E5%8F%91%E7%9A%84%E8%A1%80%E6%A1%88/ - 熟悉我的人(谁熟悉你啊🙄)知道我以前写过 PHP,虽然现在在工作中没用到了,但是自己的一些小工具还是会用 PHP 来写,但是在 Mac 碰到了一个环境相关的问题,因为我也是个更新狂魔,用了 brew 之后因为 gfw 的原因,如果长时间不更新,有时候要装一个用它装一个软件的话,前置的更新耗时就会让人非常头大,所以我基本会隔天 update 一下,但是这样会带来一个很心烦的问题,就是像这样,因为我是要用一个固定版本的 PHP,如果一直升需要一直配扩展啥的也很麻烦,如果一直升级 PHP 到最新版可能会比较少碰到这个问题

          -
          dyld: Library not loaded: /usr/local/opt/icu4c/lib/libicui18n.64.dylib
          -

          这是什么鬼啊,然后我去这个目录下看了下,已经都是libicui18n.67.dylib了,而且它没有把原来的版本保留下来,首先这个是个叫 icu4c是啥玩意,谷歌了一下

          -
          -

          ICU4C是ICU在C/C++平台下的版本, ICU(International Component for Unicode)是基于”IBM公共许可证”的,与开源组织合作研究的, 用于支持软件国际化的开源项目。ICU4C提供了C/C++平台强大的国际化开发能力,软件开发者几乎可以使用ICU4C解决任何国际化的问题,根据各地的风俗和语言习惯,实现对数字、货币、时间、日期、和消息的格式化、解析,对字符串进行大小写转换、整理、搜索和排序等功能,必须一提的是,ICU4C提供了强大的BIDI算法,对阿拉伯语等BIDI语言提供了完善的支持。

          -
          -

          然后首先想到的解决方案就是能不能我使用brew install icu4c@64来重装下原来的版本,发现不行,并木有,之前的做法就只能是去网上把 64 的下载下来,然后放到这个目录,比较麻烦不智能,虽然没抱着希望在谷歌着,不过这次竟然给我找到了一个我认为非常 nice 的解决方案,因为是在 Stack Overflow 找到的,本着写给像我这样的小小白看的,那就稍微翻译一下
          第一步,我们到 brew的目录下

          -
          cd $(brew --prefix)/Homebrew/Library/Taps/homebrew/homebrew-core/Formula
          -

          这个可以理解为是 maven 的 pom 文件,不过有很多不同之处,使用ruby 写的,然后一个文件对应一个组件或者软件,那我们看下有个叫icu4c.rb的文件,
          第二步看看它的提交历史

          -
          git log --follow icu4c.rb
          -

          在 git log 的海洋中寻找,寻找它的(64版本)的身影

          第三步注意这三个红框,Stack Overflow 给出来的答案这一步是找到这个 commit id 直接切出一个新分支

          -
          git checkout -b icu4c-63 e7f0f10dc63b1dc1061d475f1a61d01b70ef2cb7
          -

          其实注意 commit id 旁边的红框,这个是有tag 的,可以直接

          -
          git checkout icu4c-64
          -

          PS: 因为我的问题是出在 64 的问题,Stack Overflow 回答的是 63 的,反正是一样的解决方法
          第四部,切回去之后我们就可以用 brew 提供的基于文件的安装命令来重新装上 64 版本

          -
          brew reinstall ./icu4c.rb
          -

          然后就是第五步,切换版本

          -
          brew switch icu4c 64.2
          -

          最后把分支切回来

          -
          git checkout master
          -

          是不是感觉很厉害的解决方法,大佬还提供了一个更牛的,直接写个 zsh 方法

          -
          # zsh
          -function hiicu64() {
          -  local last_dir=$(pwd)
          -
          -  cd $(brew --prefix)/Homebrew/Library/Taps/homebrew/homebrew-core/Formula
          -  git checkout icu4c-4
          -  brew reinstall ./icu4c.rb
          -  brew switch icu4c 64.2
          -  git checkout master
          -
          -  cd $last_dir
          -}
          -

          对应自己的版本改改版本号就可以了,非常好用。

          -]]>
          - - Mac - PHP - Homebrew - icu4c - - - Mac - PHP - Homebrew - icu4c - zsh - -
          - - 聊聊厦门旅游的好与不好 - /2021/04/11/%E8%81%8A%E8%81%8A%E5%8E%A6%E9%97%A8%E6%97%85%E6%B8%B8%E7%9A%84%E5%A5%BD%E4%B8%8E%E4%B8%8D%E5%A5%BD/ - 这几天去了趟厦门,原来几年前就想去了,本来都请好假了,后面因为一些事情没去成,这次刚好公司组织,就跟 LD 一起去了厦门,也不洋洋洒洒地写游记了,后面可能会有,今天先来总结下好的地方和比较坑的地方。
          这次主要去了中山路、鼓浪屿、曾厝(cuo)垵、植物园、灵玲马戏团,因为住的离环岛路比较近,还有幸现场看了下厦门马拉松,其中

          -

          中山路

          这里看上去是有点民国时期的建筑风格,部分像那种电视里的租界啥的,不过这次去的时候都在翻修,路一大半拦起来了,听导游说这里往里面走有个局口街,然后上次听前同事说厦门比较有名的就是沙茶面和海蛎煎,不出意料的不太爱吃,沙茶面比较普通,可能是没吃到正宗的,海蛎煎吃不惯,倒是有个大叔的沙茶里脊还不错,在局口街那,还有小哥在那拍,应该也算是个网红打卡点了,然后吃了个油条麻糍也还不错,总体如果是看建筑的话可能最近不是个好时间,个人也没这方面爱好,吃的话最好多打听打听沙茶面跟海蛎煎哪里正宗。如果不知道哪家好吃,也不爱看这类建筑的可以排个坑。

          -

          鼓浪屿

          鼓浪屿也是完全没啥概念,需要乘船过去,但是只要二十分钟,岛上没有机动车,基本都靠走,有几个比较有名的地方,菽庄花园,里面有钢琴博物馆,对这个感兴趣的可以去看看,旁边是沙滩还可以逛逛,然后有各种博物馆,风琴啥的,岛上最大的特色是巷子多,道听途说有三百多条小巷,还有几个网红打卡点,周杰伦晴天墙,还有个最美转角,都是挤满了人排队打卡拍照,不过如果不着急,慢慢悠悠逛逛还是不错的,比较推荐,推荐值☆☆

          -

          曾厝垵

          一直读不对这个字,都是叫:那个曾什么垵,愧对语文老师,这里到算是意外之喜,鼓浪屿回来已经挺累了,不过由于比较饿(什么原因后面说),并且离住的地方不远,就过去逛了逛,东西还蛮好吃的,芒果挺便宜,一大杯才十块,无骨鸡爪很贵,不是特别爱,臭豆腐不错的,也不算很贵,这里想起来,那边八婆婆的豆乳烧仙草还不错的,去中山路那会喝了,来曾厝垵也买了,奶茶爱好者可以试试,含糖量应该很高,不爱甜食或者减肥的同学慎重考虑好了再尝试,晚上那边从牌坊出来,沿着环岛路挺多夜宵店什么的,非常推荐,推荐值☆☆☆☆

          -

          植物园

          植物园还是挺名副其实的,有热带植物,沙漠多肉,因为赶时间逛得不多,热带雨林植物那太多人了,都是在那拍照,而且我指的拍照都是拍人照,本身就很小的路,各种十八线网红,或者普通游客在那摆 pose 拍照,挺无语的;沙漠多肉比较惊喜,好多比人高的仙人掌,一大片的仙人球,很可恶的是好多大仙人掌上都有人刻字,越来越体会到,我们社会人多了,什么样的都有,而且不少;还看了下百花厅,但没什么特别的,可能赶时间比较着急,没仔细看,比较推荐,推荐值☆☆☆

          -

          灵玲马戏团

          对这个其实比较排斥,主要是比较晚了,跑的有点远(我太懒了),一开始真的挺拉低体验感受的,上来个什么书法家,现场画马,卖画;不过后面的还算值回票价,主题是花木兰,空中动作应该很考验基本功,然后那些老外的飞轮还跳绳(不知道学名叫啥),动物那块不太忍心看,应该是吃了不少苦头,不过人都这样就往后点再心疼动物吧。

          -

          总结

          厦门是个非常适合干饭人的地方,吃饭的地方大部分是差不多一桌菜十个左右就完了,而且上来就一大碗饭,一瓶雪碧一瓶可乐,对于经常是家里跟亲戚吃饭都得十几二十个菜的乡下人来说,不太吃得惯这样的🤦‍♂️,当然很有可能是我们预算不足,点的差。但是有一点是我回杭州深有感触的,感觉杭州司机的素质真的是跟厦门的司机差了比较多,杭州除非公交车停了,否则人行道很难看到主动让人的,当然这里拿厦门这个旅游城市来对比也不是很公平,不过这也是体现城市现代化文明水平的一个维度吧。

          -]]>
          - - 生活 - 旅游 - - - 生活 - 杭州 - 旅游 - 厦门 - 中山路 - 局口街 - 鼓浪屿 - 曾厝垵 - 植物园 - 马戏团 - 沙茶面 - 海蛎煎 + Java + ThreadLocal + 弱引用 + 内存泄漏 + WeakReference
          @@ -13772,6 +13787,30 @@ function hiicu64() { 电瓶车 + + 聊聊我刚学会的应用诊断方法 + /2020/05/22/%E8%81%8A%E8%81%8A%E6%88%91%E5%88%9A%E5%AD%A6%E4%BC%9A%E7%9A%84%E5%BA%94%E7%94%A8%E8%AF%8A%E6%96%AD%E6%96%B9%E6%B3%95/ + 因为传说中的出身问题,我以前写的是PHP,在使用 swoole 之前,基本的应用调试手段就是简单粗暴的 var_dump,exit,对于单进程模型的 PHP 也是简单有效,技术栈换成 Java 之后,就变得没那么容易,一方面是需要编译,另一方面是一般都是基于 spring 的项目,如果问题定位比较模糊,那框架层的是很难靠简单的 System.out.println 或者打 log 解决,(PS:我觉得可能我写的东西比较适合从 PHP 这种弱类型语言转到 Java 的小白同学)这个时候一方面因为是 Java,有了非常好用的 idea IDE 的支持,可以各种花式调试,条件断点尤其牛叉,但是又因为有 Spring+Java 的双重原因,有些情况下单步调试可以把手按废掉,这也是我之前一直比较困惑苦逼的点,后来随着慢慢精(jiang)进(you)之后,比如对于一个 oom 的情况,我们可以通过启动参数加上-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=xx/xx 来配置溢出时的堆dump 日志,获取到这个文件后,我们可以通过像 Memory Analyzer (MAT)[https://www.eclipse.org/mat/] (The Eclipse Memory Analyzer is a fast and feature-rich Java heap analyzer that helps you find memory leaks and reduce memory consumption.)来查看诊断问题所在,之前用到的时候是因为有个死循环一直往链表里塞数据,属于比较简单的,后来一次是由于运维进行应用迁移时按默认的统一配置了堆内存大小,导致内存的确不够用,所以溢出了,
          今天想说的其实主要是我们的 thread dump,这也是我最近才真正用的一个方法,可能真的很小白了,用过 ide 的单步调试其实都知道会有一个一层层的玩意,比如函数从 A,调用了 B,再从 B 调用了 C,一直往下(因为是 Java,所以还有很多🤦‍♂️),这个其实也是大部分语言的调用模型,利用了栈这个数据结构,通过这个结构我们可以知道代码的调用链路,由于对于一个 spring 应用,在本身框架代码量非常庞大的情况下,外加如果应用代码也是非常多的时候,有时候通过单步调试真的很难短时间定位到问题,需要非常大的耐心和仔细观察,当然不是说完全不行,举个例子当我的应用经常启动需要非常长的时间,因为本身应用有非常多个 bean,比较难说究竟是 bean 的加载的确很慢还是有什么异常原因,这种时候就可以使用 thread dump 了,具体怎么操作呢

          如果在idea 中运行或者调试时,可以直接点击这个照相机一样的按钮,右边就会出现了左边会显示所有的线程,右边会显示线程栈,

          +
          "main@1" prio=5 tid=0x1 nid=NA runnable
          +  java.lang.Thread.State: RUNNABLE
          +	  at TreeDistance.treeDist(TreeDistance.java:64)
          +	  at TreeDistance.treeDist(TreeDistance.java:65)
          +	  at TreeDistance.treeDist(TreeDistance.java:65)
          +	  at TreeDistance.treeDist(TreeDistance.java:65)
          +	  at TreeDistance.main(TreeDistance.java:45)
          +

          这就是我们主线程的堆栈信息了,main 表示这个线程名,prio表示优先级,默认是 5,tid 表示线程 id,nid 表示对应的系统线程,后面的runnable 表示目前线程状态,因为是被我打了断点,所以是就许状态,然后下面就是对应的线程栈内容了,在TreeDistance类的 treeDist方法中,对应的文件行数是 64 行。
          这里使用 thread dump一般也不会是上面我截图代码里的这种代码量很少的,一般是大型项目,有时候跑着跑着没反应,又不知道跑到哪了,特别是一些刚接触的大项目或者需要定位一个大项目的一个疑难问题,一时没思路时,可以使用这个方法,个人觉得非常有帮助。

          +]]>
          + + Java + Thread dump + 问题排查 + 工具 + + + Java + Thread dump + +
          聊聊我理解的分布式事务 /2020/05/17/%E8%81%8A%E8%81%8A%E6%88%91%E7%90%86%E8%A7%A3%E7%9A%84%E5%88%86%E5%B8%83%E5%BC%8F%E4%BA%8B%E5%8A%A1/ @@ -13816,30 +13855,6 @@ function hiicu64() { 3PC - - 聊聊我刚学会的应用诊断方法 - /2020/05/22/%E8%81%8A%E8%81%8A%E6%88%91%E5%88%9A%E5%AD%A6%E4%BC%9A%E7%9A%84%E5%BA%94%E7%94%A8%E8%AF%8A%E6%96%AD%E6%96%B9%E6%B3%95/ - 因为传说中的出身问题,我以前写的是PHP,在使用 swoole 之前,基本的应用调试手段就是简单粗暴的 var_dump,exit,对于单进程模型的 PHP 也是简单有效,技术栈换成 Java 之后,就变得没那么容易,一方面是需要编译,另一方面是一般都是基于 spring 的项目,如果问题定位比较模糊,那框架层的是很难靠简单的 System.out.println 或者打 log 解决,(PS:我觉得可能我写的东西比较适合从 PHP 这种弱类型语言转到 Java 的小白同学)这个时候一方面因为是 Java,有了非常好用的 idea IDE 的支持,可以各种花式调试,条件断点尤其牛叉,但是又因为有 Spring+Java 的双重原因,有些情况下单步调试可以把手按废掉,这也是我之前一直比较困惑苦逼的点,后来随着慢慢精(jiang)进(you)之后,比如对于一个 oom 的情况,我们可以通过启动参数加上-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=xx/xx 来配置溢出时的堆dump 日志,获取到这个文件后,我们可以通过像 Memory Analyzer (MAT)[https://www.eclipse.org/mat/] (The Eclipse Memory Analyzer is a fast and feature-rich Java heap analyzer that helps you find memory leaks and reduce memory consumption.)来查看诊断问题所在,之前用到的时候是因为有个死循环一直往链表里塞数据,属于比较简单的,后来一次是由于运维进行应用迁移时按默认的统一配置了堆内存大小,导致内存的确不够用,所以溢出了,
          今天想说的其实主要是我们的 thread dump,这也是我最近才真正用的一个方法,可能真的很小白了,用过 ide 的单步调试其实都知道会有一个一层层的玩意,比如函数从 A,调用了 B,再从 B 调用了 C,一直往下(因为是 Java,所以还有很多🤦‍♂️),这个其实也是大部分语言的调用模型,利用了栈这个数据结构,通过这个结构我们可以知道代码的调用链路,由于对于一个 spring 应用,在本身框架代码量非常庞大的情况下,外加如果应用代码也是非常多的时候,有时候通过单步调试真的很难短时间定位到问题,需要非常大的耐心和仔细观察,当然不是说完全不行,举个例子当我的应用经常启动需要非常长的时间,因为本身应用有非常多个 bean,比较难说究竟是 bean 的加载的确很慢还是有什么异常原因,这种时候就可以使用 thread dump 了,具体怎么操作呢

          如果在idea 中运行或者调试时,可以直接点击这个照相机一样的按钮,右边就会出现了左边会显示所有的线程,右边会显示线程栈,

          -
          "main@1" prio=5 tid=0x1 nid=NA runnable
          -  java.lang.Thread.State: RUNNABLE
          -	  at TreeDistance.treeDist(TreeDistance.java:64)
          -	  at TreeDistance.treeDist(TreeDistance.java:65)
          -	  at TreeDistance.treeDist(TreeDistance.java:65)
          -	  at TreeDistance.treeDist(TreeDistance.java:65)
          -	  at TreeDistance.main(TreeDistance.java:45)
          -

          这就是我们主线程的堆栈信息了,main 表示这个线程名,prio表示优先级,默认是 5,tid 表示线程 id,nid 表示对应的系统线程,后面的runnable 表示目前线程状态,因为是被我打了断点,所以是就许状态,然后下面就是对应的线程栈内容了,在TreeDistance类的 treeDist方法中,对应的文件行数是 64 行。
          这里使用 thread dump一般也不会是上面我截图代码里的这种代码量很少的,一般是大型项目,有时候跑着跑着没反应,又不知道跑到哪了,特别是一些刚接触的大项目或者需要定位一个大项目的一个疑难问题,一时没思路时,可以使用这个方法,个人觉得非常有帮助。

          -]]>
          - - Java - Thread dump - 问题排查 - 工具 - - - Java - Thread dump - -
          聊聊最近平淡的生活之又聊通勤 /2021/11/07/%E8%81%8A%E8%81%8A%E6%9C%80%E8%BF%91%E5%B9%B3%E6%B7%A1%E7%9A%84%E7%94%9F%E6%B4%BB/ @@ -13860,99 +13875,23 @@ function hiicu64() { - 聊聊 Sharding-Jdbc 分库分表下的分页方案 - /2022/01/09/%E8%81%8A%E8%81%8A-Sharding-Jdbc-%E5%88%86%E5%BA%93%E5%88%86%E8%A1%A8%E4%B8%8B%E7%9A%84%E5%88%86%E9%A1%B5%E6%96%B9%E6%A1%88/ - 前面在聊 Sharding-Jdbc 的时候看到了一篇文章,关于一个分页的查询,一直比较直接的想法就是分库分表下的分页是非常不合理的,一般我们的实操方案都是分表加上 ES 搜索做分页,或者通过合表读写分离的方案,因为对于 sharding-jdbc 如果没有带分表键,查询基本都是只能在所有分表都执行一遍,然后再加上分页,基本上是分页越大后续的查询越耗资源,但是仔细的去想这个细节还是这次,就简单说说
          首先就是我的分表结构

          -
          CREATE TABLE `student_time_0` (
          -  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
          -  `user_id` int(11) NOT NULL,
          -  `name` varchar(200) COLLATE utf8_bin DEFAULT NULL,
          -  `age` tinyint(3) unsigned DEFAULT NULL,
          -  `create_time` bigint(20) DEFAULT NULL,
          -  PRIMARY KEY (`id`)
          -) ENGINE=InnoDB AUTO_INCREMENT=674 DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
          -

          有这样的三个表,student_time_0, student_time_1, student_time_2, 以 user_id 作为分表键,根据表数量取模作为分表依据
          这里先构造点数据,

          -
          insert into student_time (`name`, `user_id`, `age`, `create_time`) values (?, ?, ?, ?)
          -

          主要是为了保证 create_time 唯一比较好说明问题,

          -
          int i = 0;
          -try (
          -        Connection conn = dataSource.getConnection();
          -        PreparedStatement ps = conn.prepareStatement(insertSql)) {
          -    do {
          -        ps.setString(1, localName + new Random().nextInt(100));
          -        ps.setLong(2, 10086L + (new Random().nextInt(100)));
          -        ps.setInt(3, 18);
          -        ps.setLong(4, new Date().getTime());
          -
          -
          -        int result = ps.executeUpdate();
          -        LOGGER.info("current execute result: {}", result);
          -        Thread.sleep(new Random().nextInt(100));
          -        i++;
          -    } while (i <= 2000);
          -

          三个表的数据分别是 673,678,650,说明符合预期了,各个表数据不一样,接下来比如我们想要做一个这样的分页查询

          -
          select * from student_time ORDER BY create_time ASC limit 1000, 5;
          -

          student_time 对于我们使用的 sharding-jdbc 来说当然是逻辑表,首先从一无所知去想这个查询如果我们自己来处理应该是怎么做,
          首先是不是可以每个表都从 333 开始取 5 条数据,类似于下面的查询,然后进行 15 条的合并重排序获取前面的 5 条

          -
          select * from student_time_0 ORDER BY create_time ASC limit 333, 5;
          -select * from student_time_1 ORDER BY create_time ASC limit 333, 5;
          -select * from student_time_2 ORDER BY create_time ASC limit 333, 5;
          -

          忽略前面 limit 差的 1,这个结果除非三个表的分布是绝对的均匀,否则结果肯定会出现一定的偏差,以为每个表的 333 这个位置对于其他表来说都不一定是一样的,这样对于最后整体的结果,就会出现偏差
          因为一直在纠结怎么让这个更直观的表现出来,所以尝试画了个图

          黑色的框代表我从每个表里按排序从 334 到 338 的 5 条数据, 他们在每个表里都是代表了各自正确的排序值,但是对于我们想要的其实是合表后的 1001,1005 这五条,然后我们假设总的排序值位于前 1000 的分布是第 0 个表是 320 条,第 1 个表是 340 条,第 2 个表是 340 条,那么可以明显地看出来我这么查的结果简单合并肯定是不对的。
          那么 sharding-jdbc 是如何保证这个结果的呢,其实就是我在每个表里都查分页偏移量和分页大小那么多的数据,在我这个例子里就是对于 0,1,2 三个分表每个都查 1005 条数据,即使我的数据不平衡到最极端的情况,前 1005 条数据都出在某个分表中,也可以正确获得最后的结果,但是明显的问题就是大分页,数据较多,就会导致非常大的问题,即使如 sharding-jdbc 对于合并排序的优化做得比较好,也还是需要传输那么大量的数据,并且查询也耗时,那么有没有解决方案呢,应该说有两个,或者说主要是想讲后者
          第一个办法是像这种查询,如果业务上不需要进行跳页,而是只给下一页,那么我们就能把前一次的最大偏移量的 create_time 记录下来,下一页就可以拿着这个偏移量进行查询,这个比较简单易懂,就不多说了
          第二个办法是看的58 沈剑的一篇文章,尝试理解讲述一下,
          这个办法的第一步跟前面那个错误的方法或者说不准确的方法一样,先是将分页偏移量平均后在三个表里进行查询

          -
          t0
          -334 10158 nick95  18  1641548941767
          -335 10098 nick11  18  1641548941879
          -336 10167 nick51  18  1641548942089
          -337 10167 nick3 18  1641548942119
          -338 10170 nick57  18  1641548942169
          -
          -
          -t1
          -334 10105 nick98  18  1641548939071   最小
          -335 10174 nick94  18  1641548939377
          -336 10129 nick85  18  1641548939442
          -337 10141 nick84  18  1641548939480
          -338 10096 nick74  18  1641548939668
          -
          -t2
          -334 10184 nick11  18  1641548945075
          -335 10109 nick93  18  1641548945382
          -336 10181 nick41  18  1641548945583
          -337 10130 nick80  18  1641548945993
          -338 10184 nick19  18  1641548946294  最大
          -

          然后要做什么呢,其实目标比较明白,因为前面那种方法其实就是我知道了前一页的偏移量,所以可以直接当做条件来进行查询,那这里我也想着拿到这个条件,所以我将第一遍查出来的最小的 create_time 和最大的 create_time 找出来,然后再去三个表里查询,其实主要是最小值,因为我拿着最小值去查以后我就能知道这个最小值在每个表里处在什么位置,

          -
          t0
          -322 10161 nick81  18  1641548939284
          -323 10113 nick16  18  1641548939393
          -324 10110 nick56  18  1641548939577
          -325 10116 nick69  18  1641548939588
          -326 10173 nick51  18  1641548939646
          -
          -t1
          -334 10105 nick98  18  1641548939071
          -335 10174 nick94  18  1641548939377
          -336 10129 nick85  18  1641548939442
          -337 10141 nick84  18  1641548939480
          -338 10096 nick74  18  1641548939668
          -
          -t2
          -297 10136 nick28  18  1641548939161
          -298 10142 nick68  18  1641548939177
          -299 10124 nick41  18  1641548939237
          -300 10148 nick87  18  1641548939510
          -301 10169 nick23  18  1641548939715
          -

          我只贴了前五条数据,为了方便知道偏移量,每个分表都使用了自增主键,我们可以看到前一次查询的最小值分别在其他两个表里的位置分别是 322-1 和 297-1,那么对于总体来说这个时间应该是在 322 - 1 + 333 + 297 - 1 = 951,那这样子我只要对后面的数据最多每个表查 1000 - 951 + 5 = 54 条数据再进行合并排序就可以获得最终正确的结果。
          这个就是传说中的二次查询法。

          + 聊聊最近平淡的生活之看《神探狄仁杰》 + /2021/12/19/%E8%81%8A%E8%81%8A%E6%9C%80%E8%BF%91%E5%B9%B3%E6%B7%A1%E7%9A%84%E7%94%9F%E6%B4%BB%E4%B9%8B%E7%9C%8B%E3%80%8A%E7%A5%9E%E6%8E%A2%E7%8B%84%E4%BB%81%E6%9D%B0%E3%80%8B/ + 其实最近看的不止这一部,前面看了《继承者们》,《少年包青天》这些,就一起聊下,其中看《继承者们》算是个人比较喜欢,以前就有这种看剧的习惯,这个跟《一生一世》里任嘉伦说自己看《寻秦记》看了几十遍一样,我看喜欢的剧也基本上会看不止五遍,继承者们是有帅哥美女看,而且印象中剧情也挺甜的,一般情况下最好是已经有点遗忘剧情了,因为我个人觉得看剧分两种,无聊了又心情不太好,可以看些这类轻松又看过的剧,可以不完全专心地看剧,另外有心情专心看的时候,可以看一些需要思考,一些探案类的或者烧脑类。
          最近看了《神探狄仁杰》,因为跟前面看的《少年包青天》都是这类古装探案剧,正好有些感想,《少年包青天》算是儿时阴影,本来是不太会去看的,正好有一次有机会跟 LD 一起看了会就也觉得比较有意思就看了下去,不得不说,以前的这些剧还是很不错的,包括剧情和演员,第一部一共是 40 集,看的过程中也发现了大概是五个案子,平均八集一个案子,整体节奏还是比较慢的,但是基本每个案子其实都是构思得很巧妙,很久以前看过但是现在基本不太记得剧情了,每个案子在前面几集的时候基本都猜不到犯案逻辑,但是在看了狄仁杰之后,发现两部剧也有比较大的差别,少年包青天相对来说逻辑性会更强一些,个人主观觉得推理的严谨性更高,可能剧本打磨上更将就一下,而狄仁杰因为要提现他的个人强项,不比少年包青天中有公孙策一时瑜亮的情节,狄仁杰中分工明确,李元芳是个武力担当,曾泰是捧哏的,相对来说是狄仁杰在案子里从始至终地推进案情,有些甚至有些玄乎,会有一些跳脱跟不合理,有些像是狄仁杰的奇遇,不过这些想法是私人的观点,并不是想要评孰优孰劣;第二个感受是不知道是不是年代关系,特别是少年包青天,每个案件的大 boss 基本都不是个完全的坏人,甚至都是比较情有可原的可怜人,因为一些特殊原因,而好几个都是包拯身边的人,这一点其实跟狄仁杰里第一个使团惊魂案件比较类似,虎敬晖也是个人物形象比较丰满的角色,不是个标签化的淡薄形象,跟金木兰的感情和反叛行动在最后都说明的缘由,而且也有随着跟狄仁杰一起办案被其影响感化,最终为了救狄仁杰而被金木兰所杀,只是这样金木兰这个角色就会有些偏执和符号化,当然剧本肯定不是能面面俱到,这样的剧本已经比现在很多流量剧的好很多了。还想到了前阵子看的《指环王》中的白袍萨鲁曼在剧中也是个比较单薄的角色,这样的电影彪炳影史也没办法把个个人物都设计得完整有血有肉,或者说这本来也是应该有侧重点,当然其实我也不觉得指环王就是绝对的最好的,因为相对来说故事情节的复杂性等真的不如西游记,只是在 86 版之后的各种乱七八糟的翻牌和乱拍已经让这个真正的王者神话故事有点力不从心,这里边有部西游记后传是个人还比较喜欢的,虽然武打动作比较鬼畜,但是剧情基本是无敌的,在西游的架构上衍生出来这么完整丰富的故事,人物角色也都有各自的出彩点。
          说回狄仁杰,在这之前也看过徐克拍的几部狄仁杰的电影版,第一部刘德华拍得相对完成度更高,故事性也可圈可点,后面几部就是剧情拉胯,靠特效拉回来一点分,虽说这个也是所谓的狄仁杰宇宙的构思在里面但是现在来看基本是跟西游那些差不多,完全没有整体性可言,打一枪换一个地方,演员也没有延续性,剧情也是前后跳脱,没什么关联跟承上启下,导致质量层次不一,更不用谈什么狄仁杰宇宙了,不过这个事情也是难说,原因很多,现在资本都是更加趋利的,一些需要更长久时间才能有回报的投资是很难获得资本青睐,所以只能将重心投给选择一些流量明星,而本来应该将资源投给剧本打磨的基本就没了,再深入说也没意义了,社会现状就是这样。
          还有一点感想是,以前的剧里的拍摄环境还是比较惨的,看着一些房子,甚至皇宫都是比较破旧的,地面还是石板这种,想想以前的演员的环境再想想现在的,比如成龙说的,以前他拍剧就是啪摔了,问这条有没有过,过了就直接送医院,而不是现在可能手蹭破点皮就大叫,甚至还有饭圈这些破事。

          ]]>
          - Java + 生活 - Java - Sharding-Jdbc + 生活 + 看剧
          - 聊聊最近平淡的生活之看《神探狄仁杰》 - /2021/12/19/%E8%81%8A%E8%81%8A%E6%9C%80%E8%BF%91%E5%B9%B3%E6%B7%A1%E7%9A%84%E7%94%9F%E6%B4%BB%E4%B9%8B%E7%9C%8B%E3%80%8A%E7%A5%9E%E6%8E%A2%E7%8B%84%E4%BB%81%E6%9D%B0%E3%80%8B/ - 其实最近看的不止这一部,前面看了《继承者们》,《少年包青天》这些,就一起聊下,其中看《继承者们》算是个人比较喜欢,以前就有这种看剧的习惯,这个跟《一生一世》里任嘉伦说自己看《寻秦记》看了几十遍一样,我看喜欢的剧也基本上会看不止五遍,继承者们是有帅哥美女看,而且印象中剧情也挺甜的,一般情况下最好是已经有点遗忘剧情了,因为我个人觉得看剧分两种,无聊了又心情不太好,可以看些这类轻松又看过的剧,可以不完全专心地看剧,另外有心情专心看的时候,可以看一些需要思考,一些探案类的或者烧脑类。
          最近看了《神探狄仁杰》,因为跟前面看的《少年包青天》都是这类古装探案剧,正好有些感想,《少年包青天》算是儿时阴影,本来是不太会去看的,正好有一次有机会跟 LD 一起看了会就也觉得比较有意思就看了下去,不得不说,以前的这些剧还是很不错的,包括剧情和演员,第一部一共是 40 集,看的过程中也发现了大概是五个案子,平均八集一个案子,整体节奏还是比较慢的,但是基本每个案子其实都是构思得很巧妙,很久以前看过但是现在基本不太记得剧情了,每个案子在前面几集的时候基本都猜不到犯案逻辑,但是在看了狄仁杰之后,发现两部剧也有比较大的差别,少年包青天相对来说逻辑性会更强一些,个人主观觉得推理的严谨性更高,可能剧本打磨上更将就一下,而狄仁杰因为要提现他的个人强项,不比少年包青天中有公孙策一时瑜亮的情节,狄仁杰中分工明确,李元芳是个武力担当,曾泰是捧哏的,相对来说是狄仁杰在案子里从始至终地推进案情,有些甚至有些玄乎,会有一些跳脱跟不合理,有些像是狄仁杰的奇遇,不过这些想法是私人的观点,并不是想要评孰优孰劣;第二个感受是不知道是不是年代关系,特别是少年包青天,每个案件的大 boss 基本都不是个完全的坏人,甚至都是比较情有可原的可怜人,因为一些特殊原因,而好几个都是包拯身边的人,这一点其实跟狄仁杰里第一个使团惊魂案件比较类似,虎敬晖也是个人物形象比较丰满的角色,不是个标签化的淡薄形象,跟金木兰的感情和反叛行动在最后都说明的缘由,而且也有随着跟狄仁杰一起办案被其影响感化,最终为了救狄仁杰而被金木兰所杀,只是这样金木兰这个角色就会有些偏执和符号化,当然剧本肯定不是能面面俱到,这样的剧本已经比现在很多流量剧的好很多了。还想到了前阵子看的《指环王》中的白袍萨鲁曼在剧中也是个比较单薄的角色,这样的电影彪炳影史也没办法把个个人物都设计得完整有血有肉,或者说这本来也是应该有侧重点,当然其实我也不觉得指环王就是绝对的最好的,因为相对来说故事情节的复杂性等真的不如西游记,只是在 86 版之后的各种乱七八糟的翻牌和乱拍已经让这个真正的王者神话故事有点力不从心,这里边有部西游记后传是个人还比较喜欢的,虽然武打动作比较鬼畜,但是剧情基本是无敌的,在西游的架构上衍生出来这么完整丰富的故事,人物角色也都有各自的出彩点。
          说回狄仁杰,在这之前也看过徐克拍的几部狄仁杰的电影版,第一部刘德华拍得相对完成度更高,故事性也可圈可点,后面几部就是剧情拉胯,靠特效拉回来一点分,虽说这个也是所谓的狄仁杰宇宙的构思在里面但是现在来看基本是跟西游那些差不多,完全没有整体性可言,打一枪换一个地方,演员也没有延续性,剧情也是前后跳脱,没什么关联跟承上启下,导致质量层次不一,更不用谈什么狄仁杰宇宙了,不过这个事情也是难说,原因很多,现在资本都是更加趋利的,一些需要更长久时间才能有回报的投资是很难获得资本青睐,所以只能将重心投给选择一些流量明星,而本来应该将资源投给剧本打磨的基本就没了,再深入说也没意义了,社会现状就是这样。
          还有一点感想是,以前的剧里的拍摄环境还是比较惨的,看着一些房子,甚至皇宫都是比较破旧的,地面还是石板这种,想想以前的演员的环境再想想现在的,比如成龙说的,以前他拍剧就是啪摔了,问这条有没有过,过了就直接送医院,而不是现在可能手蹭破点皮就大叫,甚至还有饭圈这些破事。

          + 聊聊最近平淡的生活之《花束般的恋爱》观后感 + /2021/12/31/%E8%81%8A%E8%81%8A%E6%9C%80%E8%BF%91%E5%B9%B3%E6%B7%A1%E7%9A%84%E7%94%9F%E6%B4%BB%E4%B9%8B%E3%80%8A%E8%8A%B1%E6%9D%9F%E8%88%AC%E7%9A%84%E6%81%8B%E7%88%B1%E3%80%8B%E8%A7%82%E5%90%8E%E6%84%9F/ + 周末在领导的提议下看了豆瓣的年度榜单,本来感觉没啥心情看的,看到主演有有村架纯就觉得可以看一下,颜值即正义嘛,男主小麦跟女主小娟(后面简称小麦跟小娟)是两个在一次非常偶然的没赶上地铁末班车事件中相识,这里得说下日本这种通宵营业的店好像挺不错的,看着也挺正常,国内估计只有酒吧之类的可以。晚上去的地方是有点暗暗的,好像也有点类似酒吧,旁边有类似于 dj 那种,然后同桌的还有除了男女主的另外一对男女,也是因为没赶上地铁末班车的,但也是陌生人,然后小麦突然看到了有个非常有名的电影人,小娟竟然也认识,然后旁边那对完全不认识,还在那吹自己看过很多电影,比如《肖申克的救赎》,于是男女主都特别鄙夷地看着他们,然后他们又去了另一个有点像泡澡的地方席地而坐,他们发现了自己的鞋子都是一样的,然后在女的去上厕所的时候,小麦暗恋的学姐也来了,然后小麦就去跟学姐他们一起坐了,小娟回来后有点不开心就说去朋友家睡,幸好小麦看出来了(他竟然看出来了,本来以为应该是没填过恋爱很木讷的),就追出去,然后就去了小麦家,到了家小娟发现小麦家的书柜上的书简直就跟她自己家的一模一样,小麦还给小娟吹了头发,一起吃烤饭团,看电影,第二天送小娟上了公交,还约好了一起看木乃伊展,然而并没有交换联系方式,但是他们还是约上了一起看了木乃伊展,在餐馆就出现了片头那一幕的来源,因为餐馆他们想一起听歌,就用有线耳机一人一个耳朵听,但是旁边就有个大叔说“你们是不是不爱音乐,左右耳朵是不一样的,只有一起听才是真正的音乐”这样的话,然后的剧情有点跳,因为是指他们一直在这家餐馆吃饭,中间有他们一起出去玩情节穿插着,也是在这他们确立了关系,可以说主体就是体现了他们非常的合拍和默契,就像一些影评说的,这部电影是说如何跟百分百合拍的人分手,然后就是正常的恋爱开始啪啪啪,一直腻在床上,也没去就业说明会,后面也有讲了一点小麦带着小娟去认识他的朋友,也把小娟介绍给了他们认识,这里算是个小伏笔,后面他们分手也有这里的人的一些关系,接下去的剧情说实话我是不太喜欢的,如果一部八分的电影只是说恋爱被现实打败的话,我觉得在我这是不合格的,但是事实也是这样,小麦其实是有家里的资助,所以后面还是按自己的喜好给一些机构画点插画,小娟则要出去工作,因为小娟家庭观念也是要让她出去有正经工作,用脚指头想也能知道肯定不顺利,然后就是暂时在一家蛋糕店工作,小麦就每天去接小娟,日子过得甜甜蜜蜜,后面小娟在自己的努力下考了个什么资格证,去了一家医院还是什么做前台行政,这中间当然就有父母来见面吃饭了,他们在开始恋爱不久就同居合租了,然后小娟父母就是来说要让她有个正经工作,对男的说的话就是人生就是责任这类的话,而小麦爸爸算是个导火索,因为小麦家里是做烟花生意的,他爸让他就做烟花生意,因为要回老家,并且小麦也不想做,所以就拒绝了,然后他爸就说不给他每个月五万的资助,这也导致了小麦需要去找工作,这个过程也是很辛苦,本来想要年前找好工作,然后事与愿违,后面有一次小娟被同事吐槽怎么从来不去团建,于是她就去了(我以为会拒绝),正在团建的时候小麦给她电话,说找到工作了,是一个创业物流公司这种,这里剧情就是我觉得比较俗套的,小麦各种被虐,累成狗,但是就像小娟爸爸说的话,人生就是责任,所以一直在坚持,但是这样也导致了跟小娟的交流也越来越少,他们原来最爱的漫画,爱玩的游戏,也只剩小娟一个人看,一个人玩,而正是这个时候,小娟说她辞掉了工作,去做一个不是太靠谱的漫画改造的密室逃脱,然后这里其实有一点后面争议很大的,就是这个工作其实是前面小麦介绍给小娟的那些朋友中一个的女朋友介绍的,而在有个剧情就是小娟有一次在这个密室逃脱的老板怀里醒过来,是在 KTV 那样的场景里,这就有很多人觉得小娟是不是出轨了,我觉得其实不那么重要,因为这个离职的事情已经让一切矛盾都摆在眼前,小麦其实是接受这种需要承担责任的生活,也想着要跟小娟结婚,但是小娟似乎还是想要过着那样理想的生活,做自己想做的事情,看自己爱看的漫画,也要小麦能像以前那样一直那么默契的有着相同的爱好,这里的触发点其实还有个是那个小麦的朋友(也就是他女朋友介绍小娟那个不靠谱工作的)的葬礼上,小麦在参加完葬礼后有挺多想倾诉的,而小娟只是想睡了,这个让小麦第二天起来都不想理小娟,只是这里我不太理解,难道这点闹情绪都不能接受吗,所谓的合拍也只是毫无限制的情况下的合拍吧,真正的生活怎么可能如此理想呢,即使没有物质生活的压力,也会有其他的各种压力和限制,在这之后其实小麦想说的是小娟是不是没有想跟自己继续在一起的想法了,而小娟觉得都不说话了,还怎么结婚呢,后面其实导演搞了个小 trick,突然放了异常婚礼,但是不是男女主的,我并不觉得这个桥段很好,在婚礼里男女主都觉得自己想要跟对方说分手了,但是当他们去了最开始一直去的餐馆的时候,一个算是一个现实映照的就是他们一直坐的位子被占了,可能也是导演想通过这个来说明他们已经回不去了,在餐馆交谈的时候,小麦其实是说他们结婚吧,并没有想前面婚礼上预设地要分手,但是小娟放弃了,不想结婚,因为不想过那样的生活了,而小麦觉得可能生活就是那样,不可能一直保持刚恋爱时候的那种感觉,生活就是责任,人生就意味着责任。

          +

          我的一些观点也在前面说了,恋爱到婚姻,即使物质没问题,经济没问题,也会有各种各样的问题,需要一起去解决,因为结婚就意味着需要相互扶持,而不是各取所需,可能我的要求比较高,后面男女主在分手后还一起住了一段时间,我原来还在想会不会通过这个方式让他们继续去磨合同步,只是我失望了,最后给个打分可能是 5 到 6 分吧,勉强及格,好的影视剧应该源于生活高于生活,这一部可能还比不上生活。

          ]]>
          生活 @@ -13998,6 +13937,22 @@ t2 修电脑的
          + + 聊聊这次换车牌及其他 + /2022/02/20/%E8%81%8A%E8%81%8A%E8%BF%99%E6%AC%A1%E6%8D%A2%E8%BD%A6%E7%89%8C%E5%8F%8A%E5%85%B6%E4%BB%96/ + 去年 8 月份运气比较好,摇到了车牌,本来其实应该很早就开始摇的,前面第一次换工作没注意社保断缴了一个月,也是大意失荆州,后面到了 17 年社保满两年了,好像只摇了一次,还是就没摇过,有点忘了,好像是什么原因导致那次也没摇成功,但是后面暂住证就取消了,需要居住证,居住证又要一年及以上的租房合同,并且那会买车以后也不怎么开,住的地方车位还好,但是公司车位一个月要两三千,甚至还是打车上下班比较实惠,所以也没放在心上,后面摇到房以后,也觉得应该准备起来车子,就开始办了居住证,居住证其实还可以用劳动合同,而且办起来也挺快,大概是三四月份开始摇,到 8 月份的某一天收到短信说摇到了,一开始还挺开心,不过心里抱着也不怎么开,也没怎么大放在心上,不过这里有一点就是我把那个照片直接发出去,上面有着我的身份证号,被 LD 说了一顿,以后也应该小心点,但是后面不知道是哪里看了下,说杭州上牌已经需要国六标准的车了,瞬间感觉是空欢喜了,可是有同事说是可以的,我就又打了官方的电话,结果说可以的,要先转籍,然后再做上牌。

          +

          转籍其实是很方便的,在交警 12123 App 上申请就行了,在转籍以后,需要去实地验车,验车的话,在支付宝-杭州交警生活号里进行预约,找就近的车管所就好,需要准备一些东西,首先是行驶证,机动车登记证书,身份证,居住证,还有车上需要准备的东西是要有三脚架和反光背心,反光背心是最近几个月开始要的,问过之前去验车的只需要三脚架就好了,预约好了的话建议是赶上班时间越早越好,不然过去排队时间要很久,而且人多了以后会很乱,各种插队,而且有很多都是汽车销售,一个销售带着一堆车,我们附近那个进去的小路没一会就堵满车,进去需要先排队,然后扫码,接着交资料,这两个都排着队,如果去晚了就要排很久的队,交完资料才是排队等验车,验车就是打开引擎盖,有人会帮忙拓印发动机车架号,然后验车的会各种检查一下,车里面,还有后备箱,建议车内整理干净点,后备箱不要放杂物,检验完了之后,需要把三脚架跟反光背心放在后备箱盖子上,人在旁边拍个照,然后需要把车牌遮住后再拍个车子的照片,再之后就是去把车牌卸了,这个多吐槽下,那边应该是本来那边师傅帮忙卸车牌,结果他就说是教我们拆,虽然也不算难,但是不排除师傅有在偷懒,完了之后就是把旧车牌交回去,然后需要在手机上(警察叔叔 App)提交各种资料,包括身份证,行驶证,机动车登记证书,提交了之后就等寄车牌过来了。

          +

          这里面缺失的一个环节就是选号了,选号杭州有两个方式,一种就是根据交管局定期发布的选号号段,可以自定义拼 20 个号,在手机上的交警 12123 App 上可以三个一组的形式提交,如果有没被选走的,就可以预选到这个了,但是这种就是也需要有一定策略,最新出的号段能选中的概率大一点,然后数字全是 8,6 这种的肯定会一早就被选走,然后如果跟我一样可以提前选下尾号,因为尾号数字影响限号,我比较有可能周五回家,所以得避开 5,0 的,第二种就是 50 选一跟以前新车选号一样,就不介绍了。第一种选中了以后可以在前面交还旧车牌的时候填上等着寄过来了,因为我是第一种选中的,第二种也可以在手机上选,也在可以在交还车牌的时候现场选。

          +

          总体过程其实是 LD 在各种查资料跟帮我跑来跑去,要不是 LD,估计在交管局那边我就懵逼了,各种插队,而且车子开着车子,也不能随便跑,所以建议办这个的时候有个人一起比较好。

          +]]>
          + + 生活 + + + 生活 + 换车牌 + +
          聊聊那些加塞狗 /2021/01/17/%E8%81%8A%E8%81%8A%E9%82%A3%E4%BA%9B%E5%8A%A0%E5%A1%9E%E7%8B%97/ @@ -14087,33 +14042,78 @@ t2 - 聊聊最近平淡的生活之《花束般的恋爱》观后感 - /2021/12/31/%E8%81%8A%E8%81%8A%E6%9C%80%E8%BF%91%E5%B9%B3%E6%B7%A1%E7%9A%84%E7%94%9F%E6%B4%BB%E4%B9%8B%E3%80%8A%E8%8A%B1%E6%9D%9F%E8%88%AC%E7%9A%84%E6%81%8B%E7%88%B1%E3%80%8B%E8%A7%82%E5%90%8E%E6%84%9F/ - 周末在领导的提议下看了豆瓣的年度榜单,本来感觉没啥心情看的,看到主演有有村架纯就觉得可以看一下,颜值即正义嘛,男主小麦跟女主小娟(后面简称小麦跟小娟)是两个在一次非常偶然的没赶上地铁末班车事件中相识,这里得说下日本这种通宵营业的店好像挺不错的,看着也挺正常,国内估计只有酒吧之类的可以。晚上去的地方是有点暗暗的,好像也有点类似酒吧,旁边有类似于 dj 那种,然后同桌的还有除了男女主的另外一对男女,也是因为没赶上地铁末班车的,但也是陌生人,然后小麦突然看到了有个非常有名的电影人,小娟竟然也认识,然后旁边那对完全不认识,还在那吹自己看过很多电影,比如《肖申克的救赎》,于是男女主都特别鄙夷地看着他们,然后他们又去了另一个有点像泡澡的地方席地而坐,他们发现了自己的鞋子都是一样的,然后在女的去上厕所的时候,小麦暗恋的学姐也来了,然后小麦就去跟学姐他们一起坐了,小娟回来后有点不开心就说去朋友家睡,幸好小麦看出来了(他竟然看出来了,本来以为应该是没填过恋爱很木讷的),就追出去,然后就去了小麦家,到了家小娟发现小麦家的书柜上的书简直就跟她自己家的一模一样,小麦还给小娟吹了头发,一起吃烤饭团,看电影,第二天送小娟上了公交,还约好了一起看木乃伊展,然而并没有交换联系方式,但是他们还是约上了一起看了木乃伊展,在餐馆就出现了片头那一幕的来源,因为餐馆他们想一起听歌,就用有线耳机一人一个耳朵听,但是旁边就有个大叔说“你们是不是不爱音乐,左右耳朵是不一样的,只有一起听才是真正的音乐”这样的话,然后的剧情有点跳,因为是指他们一直在这家餐馆吃饭,中间有他们一起出去玩情节穿插着,也是在这他们确立了关系,可以说主体就是体现了他们非常的合拍和默契,就像一些影评说的,这部电影是说如何跟百分百合拍的人分手,然后就是正常的恋爱开始啪啪啪,一直腻在床上,也没去就业说明会,后面也有讲了一点小麦带着小娟去认识他的朋友,也把小娟介绍给了他们认识,这里算是个小伏笔,后面他们分手也有这里的人的一些关系,接下去的剧情说实话我是不太喜欢的,如果一部八分的电影只是说恋爱被现实打败的话,我觉得在我这是不合格的,但是事实也是这样,小麦其实是有家里的资助,所以后面还是按自己的喜好给一些机构画点插画,小娟则要出去工作,因为小娟家庭观念也是要让她出去有正经工作,用脚指头想也能知道肯定不顺利,然后就是暂时在一家蛋糕店工作,小麦就每天去接小娟,日子过得甜甜蜜蜜,后面小娟在自己的努力下考了个什么资格证,去了一家医院还是什么做前台行政,这中间当然就有父母来见面吃饭了,他们在开始恋爱不久就同居合租了,然后小娟父母就是来说要让她有个正经工作,对男的说的话就是人生就是责任这类的话,而小麦爸爸算是个导火索,因为小麦家里是做烟花生意的,他爸让他就做烟花生意,因为要回老家,并且小麦也不想做,所以就拒绝了,然后他爸就说不给他每个月五万的资助,这也导致了小麦需要去找工作,这个过程也是很辛苦,本来想要年前找好工作,然后事与愿违,后面有一次小娟被同事吐槽怎么从来不去团建,于是她就去了(我以为会拒绝),正在团建的时候小麦给她电话,说找到工作了,是一个创业物流公司这种,这里剧情就是我觉得比较俗套的,小麦各种被虐,累成狗,但是就像小娟爸爸说的话,人生就是责任,所以一直在坚持,但是这样也导致了跟小娟的交流也越来越少,他们原来最爱的漫画,爱玩的游戏,也只剩小娟一个人看,一个人玩,而正是这个时候,小娟说她辞掉了工作,去做一个不是太靠谱的漫画改造的密室逃脱,然后这里其实有一点后面争议很大的,就是这个工作其实是前面小麦介绍给小娟的那些朋友中一个的女朋友介绍的,而在有个剧情就是小娟有一次在这个密室逃脱的老板怀里醒过来,是在 KTV 那样的场景里,这就有很多人觉得小娟是不是出轨了,我觉得其实不那么重要,因为这个离职的事情已经让一切矛盾都摆在眼前,小麦其实是接受这种需要承担责任的生活,也想着要跟小娟结婚,但是小娟似乎还是想要过着那样理想的生活,做自己想做的事情,看自己爱看的漫画,也要小麦能像以前那样一直那么默契的有着相同的爱好,这里的触发点其实还有个是那个小麦的朋友(也就是他女朋友介绍小娟那个不靠谱工作的)的葬礼上,小麦在参加完葬礼后有挺多想倾诉的,而小娟只是想睡了,这个让小麦第二天起来都不想理小娟,只是这里我不太理解,难道这点闹情绪都不能接受吗,所谓的合拍也只是毫无限制的情况下的合拍吧,真正的生活怎么可能如此理想呢,即使没有物质生活的压力,也会有其他的各种压力和限制,在这之后其实小麦想说的是小娟是不是没有想跟自己继续在一起的想法了,而小娟觉得都不说话了,还怎么结婚呢,后面其实导演搞了个小 trick,突然放了异常婚礼,但是不是男女主的,我并不觉得这个桥段很好,在婚礼里男女主都觉得自己想要跟对方说分手了,但是当他们去了最开始一直去的餐馆的时候,一个算是一个现实映照的就是他们一直坐的位子被占了,可能也是导演想通过这个来说明他们已经回不去了,在餐馆交谈的时候,小麦其实是说他们结婚吧,并没有想前面婚礼上预设地要分手,但是小娟放弃了,不想结婚,因为不想过那样的生活了,而小麦觉得可能生活就是那样,不可能一直保持刚恋爱时候的那种感觉,生活就是责任,人生就意味着责任。

          -

          我的一些观点也在前面说了,恋爱到婚姻,即使物质没问题,经济没问题,也会有各种各样的问题,需要一起去解决,因为结婚就意味着需要相互扶持,而不是各取所需,可能我的要求比较高,后面男女主在分手后还一起住了一段时间,我原来还在想会不会通过这个方式让他们继续去磨合同步,只是我失望了,最后给个打分可能是 5 到 6 分吧,勉强及格,好的影视剧应该源于生活高于生活,这一部可能还比不上生活。

          -]]>
          - - 生活 - - - 生活 - 看剧 - -
          - - 聊聊这次换车牌及其他 - /2022/02/20/%E8%81%8A%E8%81%8A%E8%BF%99%E6%AC%A1%E6%8D%A2%E8%BD%A6%E7%89%8C%E5%8F%8A%E5%85%B6%E4%BB%96/ - 去年 8 月份运气比较好,摇到了车牌,本来其实应该很早就开始摇的,前面第一次换工作没注意社保断缴了一个月,也是大意失荆州,后面到了 17 年社保满两年了,好像只摇了一次,还是就没摇过,有点忘了,好像是什么原因导致那次也没摇成功,但是后面暂住证就取消了,需要居住证,居住证又要一年及以上的租房合同,并且那会买车以后也不怎么开,住的地方车位还好,但是公司车位一个月要两三千,甚至还是打车上下班比较实惠,所以也没放在心上,后面摇到房以后,也觉得应该准备起来车子,就开始办了居住证,居住证其实还可以用劳动合同,而且办起来也挺快,大概是三四月份开始摇,到 8 月份的某一天收到短信说摇到了,一开始还挺开心,不过心里抱着也不怎么开,也没怎么大放在心上,不过这里有一点就是我把那个照片直接发出去,上面有着我的身份证号,被 LD 说了一顿,以后也应该小心点,但是后面不知道是哪里看了下,说杭州上牌已经需要国六标准的车了,瞬间感觉是空欢喜了,可是有同事说是可以的,我就又打了官方的电话,结果说可以的,要先转籍,然后再做上牌。

          -

          转籍其实是很方便的,在交警 12123 App 上申请就行了,在转籍以后,需要去实地验车,验车的话,在支付宝-杭州交警生活号里进行预约,找就近的车管所就好,需要准备一些东西,首先是行驶证,机动车登记证书,身份证,居住证,还有车上需要准备的东西是要有三脚架和反光背心,反光背心是最近几个月开始要的,问过之前去验车的只需要三脚架就好了,预约好了的话建议是赶上班时间越早越好,不然过去排队时间要很久,而且人多了以后会很乱,各种插队,而且有很多都是汽车销售,一个销售带着一堆车,我们附近那个进去的小路没一会就堵满车,进去需要先排队,然后扫码,接着交资料,这两个都排着队,如果去晚了就要排很久的队,交完资料才是排队等验车,验车就是打开引擎盖,有人会帮忙拓印发动机车架号,然后验车的会各种检查一下,车里面,还有后备箱,建议车内整理干净点,后备箱不要放杂物,检验完了之后,需要把三脚架跟反光背心放在后备箱盖子上,人在旁边拍个照,然后需要把车牌遮住后再拍个车子的照片,再之后就是去把车牌卸了,这个多吐槽下,那边应该是本来那边师傅帮忙卸车牌,结果他就说是教我们拆,虽然也不算难,但是不排除师傅有在偷懒,完了之后就是把旧车牌交回去,然后需要在手机上(警察叔叔 App)提交各种资料,包括身份证,行驶证,机动车登记证书,提交了之后就等寄车牌过来了。

          -

          这里面缺失的一个环节就是选号了,选号杭州有两个方式,一种就是根据交管局定期发布的选号号段,可以自定义拼 20 个号,在手机上的交警 12123 App 上可以三个一组的形式提交,如果有没被选走的,就可以预选到这个了,但是这种就是也需要有一定策略,最新出的号段能选中的概率大一点,然后数字全是 8,6 这种的肯定会一早就被选走,然后如果跟我一样可以提前选下尾号,因为尾号数字影响限号,我比较有可能周五回家,所以得避开 5,0 的,第二种就是 50 选一跟以前新车选号一样,就不介绍了。第一种选中了以后可以在前面交还旧车牌的时候填上等着寄过来了,因为我是第一种选中的,第二种也可以在手机上选,也在可以在交还车牌的时候现场选。

          -

          总体过程其实是 LD 在各种查资料跟帮我跑来跑去,要不是 LD,估计在交管局那边我就懵逼了,各种插队,而且车子开着车子,也不能随便跑,所以建议办这个的时候有个人一起比较好。

          + 聊聊Java中的单例模式 + /2019/12/21/%E8%81%8A%E8%81%8AJava%E4%B8%AD%E7%9A%84%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F/ + 这是个 Java 面试的高频问题,我也遇到过,以往都是觉得这类题没意思,网上一搜一大堆,也不愿意记,其实说回来,主要还是没静下心来好好去理解,今天无意中看到一个课程,基本帮我把一些疑惑的点讲清楚了,首先单例是啥意思,这个其实是有范围一说,比如我起了个Spring Boot应用,在这个应用范围内,我的常规 bean 是单例的,意味着 getBean 的时候其实永远只会拿到那一个对象,那要怎么来写一个单例呢,首先就是传说中的饿汉模式,也是最简单的

          +

          饿汉模式

          public class Singleton1 {
          +    // 首先,将构造方法变成私有的
          +    private Singleton1() {};
          +    // 创建私有静态实例,这样第一次使用的时候就会进行创建
          +    private static Singleton instance = new Singleton1();
          +
          +    // 使用这个对象都是通过这个 getInstance 来获取
          +    public static Singleton1 getInstance() {
          +        return instance;
          +    }
          +    // 瞎写一个静态方法。这里想说的是,如果我们只是要调用 Singleton.getDate(...),
          +    // 本来是不想要生成 Singleton 实例的,不过没办法,已经生成了
          +    public static Date getDate(String mode) {return new Date();}
          +}
          +

          上面借鉴了一些代码,其实这是最基本,也不会错的方法,但是正如其中getDate方法里说的问题,有时候并没有想那这个对象,但是因为我调用了这个类的静态方法,导致对象已经生成了,可能这也是饿汉模式名字的来由,不管三七二十一给你生成个单例就完事了,不管有没有用,但是这种个人觉得也没啥大问题,如果是面试的话最好说出来它的缺点

          +

          饱汉模式

          public class Singleton2 {
          +    // 首先,也是先堵死 new Singleton() 这条路,将构造方法变成私有
          +    private Singleton2() {}
          +    // 和饿汉模式相比,这边不需要先实例化出来,注意这里的 volatile,它是必须的
          +    private static volatile Singleton2 instance = null;
          +
          +    private int m = 9;
          +
          +    public static Singleton getInstance() {
          +        if (instance == null) {
          +            // 加锁
          +            synchronized (Singleton2.class) {
          +                // 这一次判断也是必须的,不然会有并发问题
          +                if (instance == null) {
          +                    instance = new Singleton2();
          +                }
          +            }
          +        }
          +        return instance;
          +    }
          +}
          +

          这里容易错的有三点,理解了其实就比较好记了

          +

          第一点,为啥不在 getInstance 上整个代码块加 synchronized,这个其实比较容易理解,就是锁的力度太大,性能太差了,这点其实也要去理解,可以举个夸张的例子,比如我一个电商的服务,如果为了避免一个人的订单出现问题,是不是可以从请求入口就把他锁住,到请求结束释放,那么里面做的事情都有保障,然而这显然不可能,因为我们想要这种竞态条件抢占资源的时间尽量减少,防止其他线程等待。
          第二点,为啥synchronized之已经检查了 instance == null,还要在里面再检查一次,这个有个术语,叫 double check lock,但是为啥要这么做呢,其实很简单,想象当有两个线程,都过了第一步为空判断,这个时候只有一个线程能拿到这个锁,另一个线程就等待了,如果不再判断一次,那么第一个线程新建完对象释放锁之后,第二个线程又能拿到锁,再去创建一个对象。
          第三点,为啥要volatile关键字,原先对它的理解是它修饰的变量在 JMM 中能及时将变量值写到主存中,但是它还有个很重要的作用,就是防止指令重排序,instance = new Singleton();这行代码其实在底层是分成三条指令执行的,第一条是在堆上申请了一块内存放这个对象,但是对象的字段啥的都还是默认值,第二条是设置对象的值,比如上面的 m 是 9,然后第三条是将这个对象和虚拟机栈上的指针建立引用关联,那么如果我不用volatile关键字,这三条指令就有可能出现重排,比如变成了 1-3-2 这种顺序,当执行完第二步时,有个线程来访问这个对象了,先判断是不是空,发现不是空的,就拿去直接用了,是不是就出现问题了,所以这个volatile也是不可缺少的

          +

          嵌套类

          public class Singleton3 {
          +
          +    private Singleton3() {}
          +    // 主要是使用了 嵌套类可以访问外部类的静态属性和静态方法 的特性
          +    private static class Holder {
          +        private static Singleton3 instance = new Singleton3();
          +    }
          +    public static Singleton3 getInstance() {
          +        return Holder.instance;
          +    }
          +}
          +

          这个我个人感觉是饿汉模式的升级版,可以在调用getInstance的时候去实例化对象,也是比较推荐的

          +

          枚举单例

          public enum Singleton {
          +    INSTANCE;
          +    
          +    public void doSomething(){
          +        //todo doSomething
          +    }
          +}
          +

          枚举很特殊,它在类加载的时候会初始化里面的所有的实例,而且 JVM 保证了它们不会再被实例化,所以它天生就是单例的。

          ]]>
          - 生活 + Java + Design Patterns + Singleton - 生活 - 换车牌 + 设计模式 + Design Patterns + 单例 + Singleton
          diff --git a/sitemap.xml b/sitemap.xml index 2c776728ff..a7ab834f80 100644 --- a/sitemap.xml +++ b/sitemap.xml @@ -1435,7 +1435,7 @@ https://nicksxs.me/ - 2022-03-27 + 2022-04-02 daily 1.0 @@ -1443,1904 +1443,1904 @@ https://nicksxs.me/tags/%E7%94%9F%E6%B4%BB/ - 2022-03-27 + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/Java/ - 2022-03-27 + https://nicksxs.me/tags/%E5%B9%B4%E7%BB%88%E6%80%BB%E7%BB%93/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/JVM/ - 2022-03-27 + https://nicksxs.me/tags/2020/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/C/ - 2022-03-27 + https://nicksxs.me/tags/2021/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E5%B9%B4%E7%BB%88%E6%80%BB%E7%BB%93/ - 2022-03-27 + https://nicksxs.me/tags/%E6%8B%96%E6%9B%B4/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/2020/ - 2022-03-27 + https://nicksxs.me/tags/Java/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/2021/ - 2022-03-27 + https://nicksxs.me/tags/JVM/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E6%8B%96%E6%9B%B4/ - 2022-03-27 + https://nicksxs.me/tags/C/ + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/leetcode/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/java/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/Binary-Tree/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/DFS/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E4%BA%8C%E5%8F%89%E6%A0%91/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E9%A2%98%E8%A7%A3/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/Linked-List/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E8%AF%BB%E5%90%8E%E6%84%9F/ - 2022-03-27 + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E5%B9%B4%E4%B8%AD%E6%80%BB%E7%BB%93/ - 2022-03-27 + https://nicksxs.me/tags/2019/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/2019/ - 2022-03-27 + https://nicksxs.me/tags/%E5%B9%B4%E4%B8%AD%E6%80%BB%E7%BB%93/ + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/c/ - 2022-03-27 + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E6%8A%80%E6%9C%AF/ - 2022-03-27 + https://nicksxs.me/tags/%E5%B9%B6%E5%8F%91/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E8%AF%BB%E4%B9%A6/ - 2022-03-27 + https://nicksxs.me/tags/j-u-c/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E5%B9%B6%E5%8F%91/ - 2022-03-27 + https://nicksxs.me/tags/aqs/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/j-u-c/ - 2022-03-27 + https://nicksxs.me/tags/condition/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/aqs/ - 2022-03-27 + https://nicksxs.me/tags/await/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/condition/ - 2022-03-27 + https://nicksxs.me/tags/signal/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/await/ - 2022-03-27 + https://nicksxs.me/tags/lock/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/signal/ - 2022-03-27 + https://nicksxs.me/tags/unlock/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/lock/ - 2022-03-27 + https://nicksxs.me/tags/%E6%8A%80%E6%9C%AF/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/unlock/ - 2022-03-27 + https://nicksxs.me/tags/%E8%AF%BB%E4%B9%A6/ + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/Apollo/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/value/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E6%B3%A8%E8%A7%A3/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/environment/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/Stream/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/Comparator/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E6%8E%92%E5%BA%8F/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/sort/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/nullsfirst/ - 2022-03-27 + 2022-04-02 + weekly + 0.2 + + + + https://nicksxs.me/tags/Disruptor/ + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/Filter/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/Interceptor/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/AOP/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/Spring/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/Tomcat/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/Servlet/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/Web/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/G1/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/GC/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/Garbage-First-Collector/ - 2022-03-27 - weekly - 0.2 - - - - https://nicksxs.me/tags/Disruptor/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E9%80%92%E5%BD%92/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/Preorder-Traversal/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/Inorder-Traversal/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E5%89%8D%E5%BA%8F/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E4%B8%AD%E5%BA%8F/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/DP/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/stack/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/min-stack/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E6%9C%80%E5%B0%8F%E6%A0%88/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/leetcode-155/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/linked-list/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/Lowest-Common-Ancestor-of-a-Binary-Tree/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/string/ - 2022-03-27 - weekly - 0.2 - - - - https://nicksxs.me/tags/Intersection-of-Two-Arrays/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/Median-of-Two-Sorted-Arrays/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/dp/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E4%BB%A3%E7%A0%81%E9%A2%98%E8%A7%A3/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/Trapping-Rain-Water/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E6%8E%A5%E9%9B%A8%E6%B0%B4/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/Leetcode-42/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/Rotate-Image/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E7%9F%A9%E9%98%B5/ - 2022-03-27 + 2022-04-02 + weekly + 0.2 + + + + https://nicksxs.me/tags/Intersection-of-Two-Arrays/ + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/Remove-Duplicates-from-Sorted-List/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/linux/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/grep/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E8%BD%AC%E4%B9%89/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/mfc/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/Maven/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/C/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/Redis/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/Distributed-Lock/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/hadoop/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/cluster/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/docker/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/mysql/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/Docker/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/namespace/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/cgroup/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/Dockerfile/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/echo/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/uname/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E5%8F%91%E8%A1%8C%E7%89%88/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/Gogs/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/Webhook/ - 2022-03-27 + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E5%8D%9A%E5%AE%A2%EF%BC%8C%E6%96%87%E7%AB%A0/ - 2022-03-27 + https://nicksxs.me/tags/Mysql/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/Mysql/ - 2022-03-27 + https://nicksxs.me/tags/Mybatis/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/Mybatis/ - 2022-03-27 + https://nicksxs.me/tags/Sql%E6%B3%A8%E5%85%A5/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/Sql%E6%B3%A8%E5%85%A5/ - 2022-03-27 + https://nicksxs.me/tags/%E5%8D%9A%E5%AE%A2%EF%BC%8C%E6%96%87%E7%AB%A0/ + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E7%BC%93%E5%AD%98/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/openresty/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/nginx/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/php/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/mq/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/im/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/redis/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E6%BA%90%E7%A0%81/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E6%B7%98%E6%B1%B0%E7%AD%96%E7%95%A5/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E5%BA%94%E7%94%A8/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/Evict/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E8%BF%87%E6%9C%9F%E7%AD%96%E7%95%A5/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/Rust/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E6%89%80%E6%9C%89%E6%9D%83/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E5%86%85%E5%AD%98%E5%88%86%E5%B8%83/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E6%96%B0%E8%AF%AD%E8%A8%80/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E5%8F%AF%E5%8F%98%E5%BC%95%E7%94%A8/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E4%B8%8D%E5%8F%AF%E5%8F%98%E5%BC%95%E7%94%A8/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E5%88%87%E7%89%87/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/spark/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/python/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/Spring-Event/ - 2022-03-27 + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/websocket/ - 2022-03-27 + https://nicksxs.me/tags/WordPress/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/swoole/ - 2022-03-27 + https://nicksxs.me/tags/%E5%B0%8F%E6%8A%80%E5%B7%A7/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/WordPress/ - 2022-03-27 + https://nicksxs.me/tags/websocket/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E5%B0%8F%E6%8A%80%E5%B7%A7/ - 2022-03-27 + https://nicksxs.me/tags/swoole/ + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/gc/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E6%A0%87%E8%AE%B0%E6%95%B4%E7%90%86/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E5%9E%83%E5%9C%BE%E5%9B%9E%E6%94%B6/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/jvm/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/MQ/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/RocketMQ/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E5%89%8A%E5%B3%B0%E5%A1%AB%E8%B0%B7/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E4%B8%AD%E9%97%B4%E4%BB%B6/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/ssh/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E7%AB%AF%E5%8F%A3%E8%BD%AC%E5%8F%91/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E5%90%90%E6%A7%BD/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E7%96%AB%E6%83%85/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E7%BE%8E%E5%9B%BD/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E5%85%AC%E4%BA%A4%E8%BD%A6/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E5%8F%A3%E7%BD%A9/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E6%9D%80%E4%BA%BA%E8%AF%9B%E5%BF%83/ - 2022-03-27 + 2022-04-02 + weekly + 0.2 + + + + https://nicksxs.me/tags/%E6%89%93%E5%8D%A1/ + 2022-04-02 + weekly + 0.2 + + + + https://nicksxs.me/tags/%E5%B9%B8%E7%A6%8F%E4%BA%86%E5%90%97/ + 2022-04-02 + weekly + 0.2 + + + + https://nicksxs.me/tags/%E8%B6%B3%E7%90%83/ + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E5%BC%80%E8%BD%A6/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E5%8A%A0%E5%A1%9E/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E7%B3%9F%E5%BF%83%E4%BA%8B/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E8%A7%84%E5%88%99/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E5%85%AC%E4%BA%A4/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E8%B7%AF%E6%94%BF%E8%A7%84%E5%88%92/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E5%9F%BA%E7%A1%80%E8%AE%BE%E6%96%BD/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E6%9D%AD%E5%B7%9E/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E5%81%A5%E5%BA%B7%E7%A0%81/ - 2022-03-27 + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E6%89%93%E5%8D%A1/ - 2022-03-27 + https://nicksxs.me/tags/%E8%BF%90%E5%8A%A8/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E5%B9%B8%E7%A6%8F%E4%BA%86%E5%90%97/ - 2022-03-27 - weekly - 0.2 - - - - https://nicksxs.me/tags/%E8%B6%B3%E7%90%83/ - 2022-03-27 - weekly - 0.2 - - - - https://nicksxs.me/tags/%E8%BF%90%E5%8A%A8/ - 2022-03-27 - weekly - 0.2 - - - - https://nicksxs.me/tags/%E5%87%8F%E8%82%A5/ - 2022-03-27 + https://nicksxs.me/tags/%E5%87%8F%E8%82%A5/ + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E8%B7%91%E6%AD%A5/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E5%B9%B2%E6%B4%BB/ - 2022-03-27 + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E5%BD%B1%E8%AF%84/ - 2022-03-27 + https://nicksxs.me/tags/scp/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E5%AF%84%E7%94%9F%E8%99%AB/ - 2022-03-27 + https://nicksxs.me/tags/git/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/git/ - 2022-03-27 + https://nicksxs.me/tags/%E5%BD%B1%E8%AF%84/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/DefaultMQPushConsumer/ - 2022-03-27 + https://nicksxs.me/tags/%E5%AF%84%E7%94%9F%E8%99%AB/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90/ - 2022-03-27 + https://nicksxs.me/tags/%E5%AD%97%E7%AC%A6%E9%9B%86/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/NameServer/ - 2022-03-27 + https://nicksxs.me/tags/%E7%BC%96%E7%A0%81/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/scp/ - 2022-03-27 + https://nicksxs.me/tags/utf8/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/SpringBoot/ - 2022-03-27 + https://nicksxs.me/tags/utf8mb4/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/cglib/ - 2022-03-27 + https://nicksxs.me/tags/utf8mb4-0900-ai-ci/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E4%BA%8B%E5%8A%A1/ - 2022-03-27 + https://nicksxs.me/tags/utf8mb4-unicode-ci/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/Druid/ - 2022-03-27 + https://nicksxs.me/tags/utf8mb4-general-ci/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E6%95%B0%E6%8D%AE%E6%BA%90%E5%8A%A8%E6%80%81%E5%88%87%E6%8D%A2/ - 2022-03-27 + https://nicksxs.me/tags/DefaultMQPushConsumer/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E4%B8%9C%E4%BA%AC%E5%A5%A5%E8%BF%90%E4%BC%9A/ - 2022-03-27 + https://nicksxs.me/tags/%E6%BA%90%E7%A0%81%E8%A7%A3%E6%9E%90/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E4%B8%BE%E9%87%8D/ - 2022-03-27 + https://nicksxs.me/tags/NameServer/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E5%B0%84%E5%87%BB/ - 2022-03-27 + https://nicksxs.me/tags/SpringBoot/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E4%B9%92%E4%B9%93%E7%90%83/ - 2022-03-27 + https://nicksxs.me/tags/cglib/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E8%B7%B3%E6%B0%B4/ - 2022-03-27 + https://nicksxs.me/tags/%E4%BA%8B%E5%8A%A1/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/Dubbo/ - 2022-03-27 + https://nicksxs.me/tags/Druid/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/RPC/ - 2022-03-27 + https://nicksxs.me/tags/%E6%95%B0%E6%8D%AE%E6%BA%90%E5%8A%A8%E6%80%81%E5%88%87%E6%8D%A2/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/SPI/ - 2022-03-27 + https://nicksxs.me/tags/%E4%B8%9C%E4%BA%AC%E5%A5%A5%E8%BF%90%E4%BC%9A/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/Adaptive/ - 2022-03-27 + https://nicksxs.me/tags/%E4%B9%92%E4%B9%93%E7%90%83/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E8%87%AA%E9%80%82%E5%BA%94%E6%8B%93%E5%B1%95/ - 2022-03-27 + https://nicksxs.me/tags/%E8%B7%B3%E6%B0%B4/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E5%AE%B9%E9%94%99%E6%9C%BA%E5%88%B6/ - 2022-03-27 + https://nicksxs.me/tags/%E4%B8%BE%E9%87%8D/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E5%AD%97%E7%AC%A6%E9%9B%86/ - 2022-03-27 + https://nicksxs.me/tags/%E5%B0%84%E5%87%BB/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E7%BC%96%E7%A0%81/ - 2022-03-27 + https://nicksxs.me/tags/Dubbo/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/utf8/ - 2022-03-27 + https://nicksxs.me/tags/RPC/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/utf8mb4/ - 2022-03-27 + https://nicksxs.me/tags/SPI/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/utf8mb4-0900-ai-ci/ - 2022-03-27 + https://nicksxs.me/tags/Adaptive/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/utf8mb4-unicode-ci/ - 2022-03-27 + https://nicksxs.me/tags/%E8%87%AA%E9%80%82%E5%BA%94%E6%8B%93%E5%B1%95/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/utf8mb4-general-ci/ - 2022-03-27 + https://nicksxs.me/tags/%E5%AE%B9%E9%94%99%E6%9C%BA%E5%88%B6/ + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/Synchronized/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E5%81%8F%E5%90%91%E9%94%81/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E8%BD%BB%E9%87%8F%E7%BA%A7%E9%94%81/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E9%87%8D%E9%87%8F%E7%BA%A7%E9%94%81/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E8%87%AA%E6%97%8B/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E7%B1%BB%E5%8A%A0%E8%BD%BD/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E5%8A%A0%E8%BD%BD/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E9%AA%8C%E8%AF%81/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E5%87%86%E5%A4%87/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E8%A7%A3%E6%9E%90/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E5%88%9D%E5%A7%8B%E5%8C%96/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E9%93%BE%E6%8E%A5/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E5%8F%8C%E4%BA%B2%E5%A7%94%E6%B4%BE/ - 2022-03-27 + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/JPS/ - 2022-03-27 + https://nicksxs.me/tags/top/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/JStack/ - 2022-03-27 + https://nicksxs.me/tags/Broker/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/JMap/ - 2022-03-27 + https://nicksxs.me/tags/JPS/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/top/ - 2022-03-27 + https://nicksxs.me/tags/JStack/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/Broker/ - 2022-03-27 + https://nicksxs.me/tags/JMap/ + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/Sharding-Jdbc/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/ThreadPool/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E7%BA%BF%E7%A8%8B%E6%B1%A0/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/FixedThreadPool/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/LimitedThreadPool/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/EagerThreadPool/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/CachedThreadPool/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/mvcc/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/read-view/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/gap-lock/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/next-key-lock/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/tags/%E5%B9%BB%E8%AF%BB/ - 2022-03-27 + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E7%BC%93%E5%AD%98%E7%A9%BF%E9%80%8F/ - 2022-03-27 + https://nicksxs.me/tags/%E7%B4%A2%E5%BC%95/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E7%BC%93%E5%AD%98%E5%87%BB%E7%A9%BF/ - 2022-03-27 + https://nicksxs.me/tags/is-null/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E7%BC%93%E5%AD%98%E9%9B%AA%E5%B4%A9/ - 2022-03-27 + https://nicksxs.me/tags/is-not-null/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E5%B8%83%E9%9A%86%E8%BF%87%E6%BB%A4%E5%99%A8/ - 2022-03-27 + https://nicksxs.me/tags/procedure/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/bloom-filter/ - 2022-03-27 + https://nicksxs.me/tags/%E7%BC%93%E5%AD%98%E7%A9%BF%E9%80%8F/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E4%BA%92%E6%96%A5%E9%94%81/ - 2022-03-27 + https://nicksxs.me/tags/%E7%BC%93%E5%AD%98%E5%87%BB%E7%A9%BF/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E7%B4%A2%E5%BC%95/ - 2022-03-27 + https://nicksxs.me/tags/%E7%BC%93%E5%AD%98%E9%9B%AA%E5%B4%A9/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/is-null/ - 2022-03-27 + https://nicksxs.me/tags/%E5%B8%83%E9%9A%86%E8%BF%87%E6%BB%A4%E5%99%A8/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/is-not-null/ - 2022-03-27 + https://nicksxs.me/tags/bloom-filter/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/procedure/ - 2022-03-27 + https://nicksxs.me/tags/%E4%BA%92%E6%96%A5%E9%94%81/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/ - 2022-03-27 + https://nicksxs.me/tags/%E8%87%AA%E5%8A%A8%E8%A3%85%E9%85%8D/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/Design-Patterns/ - 2022-03-27 + https://nicksxs.me/tags/AutoConfiguration/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E5%8D%95%E4%BE%8B/ - 2022-03-27 + https://nicksxs.me/tags/Mac/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/Singleton/ - 2022-03-27 + https://nicksxs.me/tags/PHP/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E8%87%AA%E5%8A%A8%E8%A3%85%E9%85%8D/ - 2022-03-27 + https://nicksxs.me/tags/Homebrew/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/AutoConfiguration/ - 2022-03-27 + https://nicksxs.me/tags/icu4c/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/ThreadLocal/ - 2022-03-27 + https://nicksxs.me/tags/zsh/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E5%BC%B1%E5%BC%95%E7%94%A8/ - 2022-03-27 + https://nicksxs.me/tags/%E6%97%85%E6%B8%B8/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E5%86%85%E5%AD%98%E6%B3%84%E6%BC%8F/ - 2022-03-27 + https://nicksxs.me/tags/%E5%8E%A6%E9%97%A8/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/WeakReference/ - 2022-03-27 + https://nicksxs.me/tags/%E4%B8%AD%E5%B1%B1%E8%B7%AF/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/Mac/ - 2022-03-27 + https://nicksxs.me/tags/%E5%B1%80%E5%8F%A3%E8%A1%97/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/PHP/ - 2022-03-27 + https://nicksxs.me/tags/%E9%BC%93%E6%B5%AA%E5%B1%BF/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/Homebrew/ - 2022-03-27 + https://nicksxs.me/tags/%E6%9B%BE%E5%8E%9D%E5%9E%B5/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/icu4c/ - 2022-03-27 + https://nicksxs.me/tags/%E6%A4%8D%E7%89%A9%E5%9B%AD/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/zsh/ - 2022-03-27 + https://nicksxs.me/tags/%E9%A9%AC%E6%88%8F%E5%9B%A2/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E6%97%85%E6%B8%B8/ - 2022-03-27 + https://nicksxs.me/tags/%E6%B2%99%E8%8C%B6%E9%9D%A2/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E5%8E%A6%E9%97%A8/ - 2022-03-27 + https://nicksxs.me/tags/%E6%B5%B7%E8%9B%8E%E7%85%8E/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E4%B8%AD%E5%B1%B1%E8%B7%AF/ - 2022-03-27 + https://nicksxs.me/tags/ThreadLocal/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E5%B1%80%E5%8F%A3%E8%A1%97/ - 2022-03-27 + https://nicksxs.me/tags/%E5%BC%B1%E5%BC%95%E7%94%A8/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E9%BC%93%E6%B5%AA%E5%B1%BF/ - 2022-03-27 + https://nicksxs.me/tags/%E5%86%85%E5%AD%98%E6%B3%84%E6%BC%8F/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E6%9B%BE%E5%8E%9D%E5%9E%B5/ - 2022-03-27 + https://nicksxs.me/tags/WeakReference/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E6%A4%8D%E7%89%A9%E5%9B%AD/ - 2022-03-27 + https://nicksxs.me/tags/%E6%89%B6%E6%A2%AF/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E9%A9%AC%E6%88%8F%E5%9B%A2/ - 2022-03-27 + https://nicksxs.me/tags/%E8%B8%A9%E8%B8%8F/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E6%B2%99%E8%8C%B6%E9%9D%A2/ - 2022-03-27 + https://nicksxs.me/tags/%E5%AE%89%E5%85%A8/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E6%B5%B7%E8%9B%8E%E7%85%8E/ - 2022-03-27 + https://nicksxs.me/tags/%E7%94%B5%E7%93%B6%E8%BD%A6/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E6%89%B6%E6%A2%AF/ - 2022-03-27 + https://nicksxs.me/tags/Thread-dump/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E8%B8%A9%E8%B8%8F/ - 2022-03-27 + https://nicksxs.me/tags/%E5%88%86%E5%B8%83%E5%BC%8F%E4%BA%8B%E5%8A%A1/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E5%AE%89%E5%85%A8/ - 2022-03-27 + https://nicksxs.me/tags/%E4%B8%A4%E9%98%B6%E6%AE%B5%E6%8F%90%E4%BA%A4/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E7%94%B5%E7%93%B6%E8%BD%A6/ - 2022-03-27 + https://nicksxs.me/tags/%E4%B8%89%E9%98%B6%E6%AE%B5%E6%8F%90%E4%BA%A4/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E5%88%86%E5%B8%83%E5%BC%8F%E4%BA%8B%E5%8A%A1/ - 2022-03-27 + https://nicksxs.me/tags/2PC/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E4%B8%A4%E9%98%B6%E6%AE%B5%E6%8F%90%E4%BA%A4/ - 2022-03-27 + https://nicksxs.me/tags/3PC/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E4%B8%89%E9%98%B6%E6%AE%B5%E6%8F%90%E4%BA%A4/ - 2022-03-27 + https://nicksxs.me/tags/%E9%AA%91%E8%BD%A6/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/2PC/ - 2022-03-27 + https://nicksxs.me/tags/%E7%9C%8B%E5%89%A7/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/3PC/ - 2022-03-27 + https://nicksxs.me/tags/%E8%A3%85%E7%94%B5%E8%84%91/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/Thread-dump/ - 2022-03-27 + https://nicksxs.me/tags/%E8%80%81%E7%94%B5%E8%84%91/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E9%AA%91%E8%BD%A6/ - 2022-03-27 + https://nicksxs.me/tags/360-%E5%85%A8%E5%AE%B6%E6%A1%B6/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E7%9C%8B%E5%89%A7/ - 2022-03-27 + https://nicksxs.me/tags/%E4%BF%AE%E7%94%B5%E8%84%91%E7%9A%84/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E8%A3%85%E7%94%B5%E8%84%91/ - 2022-03-27 + https://nicksxs.me/tags/%E6%8D%A2%E8%BD%A6%E7%89%8C/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E8%80%81%E7%94%B5%E8%84%91/ - 2022-03-27 + https://nicksxs.me/tags/%E7%9C%8B%E4%B9%A6/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/360-%E5%85%A8%E5%AE%B6%E6%A1%B6/ - 2022-03-27 + https://nicksxs.me/tags/%E9%AB%98%E9%80%9F/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E4%BF%AE%E7%94%B5%E8%84%91%E7%9A%84/ - 2022-03-27 + https://nicksxs.me/tags/%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E7%9C%8B%E4%B9%A6/ - 2022-03-27 + https://nicksxs.me/tags/Design-Patterns/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E9%AB%98%E9%80%9F/ - 2022-03-27 + https://nicksxs.me/tags/%E5%8D%95%E4%BE%8B/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/tags/%E6%8D%A2%E8%BD%A6%E7%89%8C/ - 2022-03-27 + https://nicksxs.me/tags/Singleton/ + 2022-04-02 weekly 0.2 @@ -3349,1008 +3349,1008 @@ https://nicksxs.me/categories/%E7%94%9F%E6%B4%BB/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/categories/Java/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/categories/%E7%94%9F%E6%B4%BB/%E5%B9%B4%E7%BB%88%E6%80%BB%E7%BB%93/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/categories/Java/JVM/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/categories/leetcode/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/categories/%E7%94%9F%E6%B4%BB/%E5%B9%B4%E7%BB%88%E6%80%BB%E7%BB%93/2020/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/categories/Java/GC/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/categories/Binary-Tree/ - 2022-03-27 - weekly - 0.2 - - - - https://nicksxs.me/categories/Linked-List/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/categories/%E5%B9%B4%E7%BB%88%E6%80%BB%E7%BB%93/ - 2022-03-27 + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/C/ - 2022-03-27 + https://nicksxs.me/categories/%E8%AF%BB%E5%90%8E%E6%84%9F/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/leetcode/java/ - 2022-03-27 + https://nicksxs.me/categories/Linked-List/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/%E8%AF%BB%E5%90%8E%E6%84%9F/ - 2022-03-27 + https://nicksxs.me/categories/%E7%94%9F%E6%B4%BB/%E5%B9%B4%E7%BB%88%E6%80%BB%E7%BB%93/2019/ + 2022-04-02 weekly 0.2 https://nicksxs.me/categories/%E7%94%9F%E6%B4%BB/%E5%B9%B4%E4%B8%AD%E6%80%BB%E7%BB%93/ - 2022-03-27 - weekly - 0.2 - - - - https://nicksxs.me/categories/%E5%B9%B4%E7%BB%88%E6%80%BB%E7%BB%93/2020/ - 2022-03-27 + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/%E7%94%9F%E6%B4%BB/%E5%B9%B4%E7%BB%88%E6%80%BB%E7%BB%93/2019/ - 2022-03-27 + https://nicksxs.me/categories/C/ + 2022-04-02 weekly 0.2 https://nicksxs.me/categories/Java/%E5%B9%B6%E5%8F%91/ - 2022-03-27 + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/leetcode/java/Binary-Tree/ - 2022-03-27 + https://nicksxs.me/categories/leetcode/java/ + 2022-04-02 weekly 0.2 https://nicksxs.me/categories/java/ - 2022-03-27 + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/%E8%AF%BB%E5%90%8E%E6%84%9F/%E6%9D%91%E4%B8%8A%E6%98%A5%E6%A0%91/ - 2022-03-27 + https://nicksxs.me/categories/%E5%B9%B4%E7%BB%88%E6%80%BB%E7%BB%93/2020/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Java/Apollo/ - 2022-03-27 + https://nicksxs.me/categories/%E8%AF%BB%E5%90%8E%E6%84%9F/%E6%9D%91%E4%B8%8A%E6%98%A5%E6%A0%91/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/leetcode/java/Linked-List/ - 2022-03-27 + https://nicksxs.me/categories/Java/Apollo/ + 2022-04-02 weekly 0.2 https://nicksxs.me/categories/Java/%E9%9B%86%E5%90%88/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/categories/%E7%94%9F%E6%B4%BB/%E5%B9%B4%E4%B8%AD%E6%80%BB%E7%BB%93/2020/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/categories/Filter/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/categories/Java/leetcode/ - 2022-03-27 + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/%E7%94%9F%E6%B4%BB/%E5%B9%B4%E4%B8%AD%E6%80%BB%E7%BB%93/2021/ - 2022-03-27 + https://nicksxs.me/categories/leetcode/java/Binary-Tree/ + 2022-04-02 weekly 0.2 https://nicksxs.me/categories/DP/ - 2022-03-27 + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/leetcode/java/Binary-Tree/DFS/ - 2022-03-27 + https://nicksxs.me/categories/%E7%94%9F%E6%B4%BB/%E5%B9%B4%E4%B8%AD%E6%80%BB%E7%BB%93/2021/ + 2022-04-02 weekly 0.2 https://nicksxs.me/categories/stack/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/categories/linked-list/ - 2022-03-27 + 2022-04-02 + weekly + 0.2 + + + + https://nicksxs.me/categories/leetcode/java/Linked-List/ + 2022-04-02 weekly 0.2 https://nicksxs.me/categories/%E5%AD%97%E7%AC%A6%E4%B8%B2-online/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/categories/Java/Apollo/value/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/categories/Linux/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/categories/Java/Maven/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/categories/Redis/ - 2022-03-27 + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Interceptor-AOP/ - 2022-03-27 + https://nicksxs.me/categories/data-analysis/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/data-analysis/ - 2022-03-27 + https://nicksxs.me/categories/Interceptor-AOP/ + 2022-04-02 weekly 0.2 https://nicksxs.me/categories/docker/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/categories/Docker/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/categories/%E6%8C%81%E7%BB%AD%E9%9B%86%E6%88%90/ - 2022-03-27 + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/leetcode/java/DP/ - 2022-03-27 + https://nicksxs.me/categories/leetcode/java/Binary-Tree/DFS/ + 2022-04-02 weekly 0.2 https://nicksxs.me/categories/Java/Mybatis/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/categories/nginx/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/categories/php/ - 2022-03-27 + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/redis/ - 2022-03-27 + https://nicksxs.me/categories/leetcode/java/DP/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/leetcode/java/stack/ - 2022-03-27 + https://nicksxs.me/categories/redis/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Java/leetcode/Lowest-Common-Ancestor-of-a-Binary-Tree/ - 2022-03-27 + https://nicksxs.me/categories/leetcode/java/stack/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/leetcode/java/linked-list/ - 2022-03-27 + https://nicksxs.me/categories/Java/leetcode/Lowest-Common-Ancestor-of-a-Binary-Tree/ + 2022-04-02 weekly 0.2 https://nicksxs.me/categories/%E8%AF%AD%E8%A8%80/ - 2022-03-27 + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Java/Spring/ - 2022-03-27 + https://nicksxs.me/categories/leetcode/java/linked-list/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/leetcode/java/string/ - 2022-03-27 + https://nicksxs.me/categories/Java/Spring/ + 2022-04-02 weekly 0.2 https://nicksxs.me/categories/%E5%B0%8F%E6%8A%80%E5%B7%A7/ - 2022-03-27 + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Java/leetcode/Rotate-Image/ - 2022-03-27 + https://nicksxs.me/categories/Java/gc/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Java/gc/ - 2022-03-27 + https://nicksxs.me/categories/%E7%94%9F%E6%B4%BB/%E8%BF%90%E5%8A%A8/ + 2022-04-02 weekly 0.2 https://nicksxs.me/categories/MQ/ - 2022-03-27 + 2022-04-02 weekly 0.2 https://nicksxs.me/categories/ssh/ - 2022-03-27 + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/%E7%94%9F%E6%B4%BB/%E5%90%90%E6%A7%BD/ - 2022-03-27 + https://nicksxs.me/categories/leetcode/java/string/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/%E7%94%9F%E6%B4%BB/%E5%85%AC%E4%BA%A4/ - 2022-03-27 + https://nicksxs.me/categories/Java/leetcode/Rotate-Image/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Linux/%E5%91%BD%E4%BB%A4/ - 2022-03-27 + https://nicksxs.me/categories/%E7%94%9F%E6%B4%BB/%E5%90%90%E6%A7%BD/ + 2022-04-02 weekly 0.2 https://nicksxs.me/categories/%E8%AF%BB%E5%90%8E%E6%84%9F/%E7%99%BD%E5%B2%A9%E6%9D%BE/ - 2022-03-27 + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/%E7%94%9F%E6%B4%BB/%E8%BF%90%E5%8A%A8/ - 2022-03-27 + https://nicksxs.me/categories/%E7%94%9F%E6%B4%BB/%E5%85%AC%E4%BA%A4/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Redis/Distributed-Lock/ - 2022-03-27 + https://nicksxs.me/categories/shell/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/%E7%94%9F%E6%B4%BB/%E5%BD%B1%E8%AF%84/ - 2022-03-27 + https://nicksxs.me/categories/git/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/git/ - 2022-03-27 + https://nicksxs.me/categories/Linux/%E5%91%BD%E4%BB%A4/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Spring/ - 2022-03-27 + https://nicksxs.me/categories/%E7%94%9F%E6%B4%BB/%E5%BD%B1%E8%AF%84/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Docker/%E4%BB%8B%E7%BB%8D/ - 2022-03-27 + https://nicksxs.me/categories/Redis/Distributed-Lock/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/shell/ - 2022-03-27 + https://nicksxs.me/categories/Spring/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Java/SpringBoot/ - 2022-03-27 + https://nicksxs.me/categories/Docker/%E4%BB%8B%E7%BB%8D/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Dubbo-RPC-SPI/ - 2022-03-27 + https://nicksxs.me/categories/Mysql/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Mysql/ - 2022-03-27 + https://nicksxs.me/categories/Mybatis/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Dubbo-RPC/ - 2022-03-27 + https://nicksxs.me/categories/Redis/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Mybatis/ - 2022-03-27 + https://nicksxs.me/categories/%E8%AF%AD%E8%A8%80/Rust/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Java/%E7%B1%BB%E5%8A%A0%E8%BD%BD/ - 2022-03-27 + https://nicksxs.me/categories/Rust/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Thread-dump/ - 2022-03-27 + https://nicksxs.me/categories/Java/gc/jvm/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Dubbo-%E7%BA%BF%E7%A8%8B%E6%B1%A0/ - 2022-03-27 + https://nicksxs.me/categories/RocketMQ/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Redis/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/ - 2022-03-27 + https://nicksxs.me/categories/ssh/%E6%8A%80%E5%B7%A7/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Redis/%E5%BA%94%E7%94%A8/ - 2022-03-27 + https://nicksxs.me/categories/%E7%94%9F%E6%B4%BB/%E5%90%90%E6%A7%BD/%E7%96%AB%E6%83%85/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Java/Design-Patterns/ - 2022-03-27 + https://nicksxs.me/categories/%E8%AF%BB%E5%90%8E%E6%84%9F/%E7%99%BD%E5%B2%A9%E6%9D%BE/%E5%B9%B8%E7%A6%8F%E4%BA%86%E5%90%97/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/SpringBoot/ - 2022-03-27 + https://nicksxs.me/categories/%E7%94%9F%E6%B4%BB/%E8%BF%90%E5%8A%A8/%E8%B7%91%E6%AD%A5/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Mac/ - 2022-03-27 + https://nicksxs.me/categories/shell/%E5%B0%8F%E6%8A%80%E5%B7%A7/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/%E7%94%9F%E6%B4%BB/%E6%97%85%E6%B8%B8/ - 2022-03-27 + https://nicksxs.me/categories/git/%E5%B0%8F%E6%8A%80%E5%B7%A7/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/%E5%88%86%E5%B8%83%E5%BC%8F%E4%BA%8B%E5%8A%A1/ - 2022-03-27 + https://nicksxs.me/categories/Linux/%E5%91%BD%E4%BB%A4/grep/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/%E7%94%9F%E6%B4%BB/%E5%BC%80%E8%BD%A6/ - 2022-03-27 + https://nicksxs.me/categories/%E7%94%9F%E6%B4%BB/%E5%BD%B1%E8%AF%84/2020/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/%E8%AF%AD%E8%A8%80/Rust/ - 2022-03-27 + https://nicksxs.me/categories/C/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Rust/ - 2022-03-27 + https://nicksxs.me/categories/Spring/Servlet/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Java/gc/jvm/ - 2022-03-27 + https://nicksxs.me/categories/Linux/%E5%91%BD%E4%BB%A4/echo/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/RocketMQ/ - 2022-03-27 + https://nicksxs.me/categories/Mysql/Sql%E6%B3%A8%E5%85%A5/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/ssh/%E6%8A%80%E5%B7%A7/ - 2022-03-27 + https://nicksxs.me/categories/Mybatis/%E7%BC%93%E5%AD%98/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/%E7%94%9F%E6%B4%BB/%E5%90%90%E6%A7%BD/%E7%96%AB%E6%83%85/ - 2022-03-27 + https://nicksxs.me/categories/Redis/%E6%BA%90%E7%A0%81/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Linux/%E5%91%BD%E4%BB%A4/grep/ - 2022-03-27 + https://nicksxs.me/categories/%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/%E8%AF%BB%E5%90%8E%E6%84%9F/%E7%99%BD%E5%B2%A9%E6%9D%BE/%E5%B9%B8%E7%A6%8F%E4%BA%86%E5%90%97/ - 2022-03-27 + https://nicksxs.me/categories/%E7%94%9F%E6%B4%BB/%E5%90%90%E6%A7%BD/%E7%96%AB%E6%83%85/%E7%BE%8E%E5%9B%BD/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/%E7%94%9F%E6%B4%BB/%E8%BF%90%E5%8A%A8/%E8%B7%91%E6%AD%A5/ - 2022-03-27 + https://nicksxs.me/categories/%E7%94%9F%E6%B4%BB/%E5%90%90%E6%A7%BD/%E7%96%AB%E6%83%85/%E5%8F%A3%E7%BD%A9/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/C/ - 2022-03-27 + https://nicksxs.me/categories/%E7%94%9F%E6%B4%BB/%E8%BF%90%E5%8A%A8/%E8%B7%91%E6%AD%A5/%E5%B9%B2%E6%B4%BB/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/%E7%94%9F%E6%B4%BB/%E5%BD%B1%E8%AF%84/2020/ - 2022-03-27 + https://nicksxs.me/categories/%E5%B0%8F%E6%8A%80%E5%B7%A7/grep/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/git/%E5%B0%8F%E6%8A%80%E5%B7%A7/ - 2022-03-27 + https://nicksxs.me/categories/C/Redis/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Spring/Servlet/ - 2022-03-27 + https://nicksxs.me/categories/Spring/Servlet/Interceptor/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/MQ/RocketMQ/ - 2022-03-27 + https://nicksxs.me/categories/Docker/%E5%8F%91%E8%A1%8C%E7%89%88%E6%9C%AC/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/shell/%E5%B0%8F%E6%8A%80%E5%B7%A7/ - 2022-03-27 + https://nicksxs.me/categories/Spring/Mybatis/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Linux/%E5%91%BD%E4%BB%A4/echo/ - 2022-03-27 + https://nicksxs.me/categories/%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97/RocketMQ/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Dubbo/ - 2022-03-27 + https://nicksxs.me/categories/%E5%B0%8F%E6%8A%80%E5%B7%A7/grep/%E6%9F%A5%E6%97%A5%E5%BF%97/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Mysql/Sql%E6%B3%A8%E5%85%A5/ - 2022-03-27 + https://nicksxs.me/categories/Spring/Servlet/Interceptor/AOP/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Mybatis/%E7%BC%93%E5%AD%98/ - 2022-03-27 + https://nicksxs.me/categories/%E4%B8%AD%E9%97%B4%E4%BB%B6/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Linux/%E5%91%BD%E4%BB%A4/top/ - 2022-03-27 + https://nicksxs.me/categories/%E4%B8%AD%E9%97%B4%E4%BB%B6/RocketMQ/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/%E9%97%AE%E9%A2%98%E6%8E%92%E6%9F%A5/ - 2022-03-27 + https://nicksxs.me/categories/MQ/RocketMQ/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Mysql/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/ - 2022-03-27 + https://nicksxs.me/categories/MQ/RocketMQ/%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Redis/%E6%BA%90%E7%A0%81/ - 2022-03-27 + https://nicksxs.me/categories/Java/SpringBoot/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Redis/%E7%BC%93%E5%AD%98/ - 2022-03-27 + https://nicksxs.me/categories/Dubbo-RPC-SPI/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Mysql/%E7%B4%A2%E5%BC%95/ - 2022-03-27 + https://nicksxs.me/categories/Dubbo-RPC/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Java/Singleton/ - 2022-03-27 + https://nicksxs.me/categories/Java/%E7%B1%BB%E5%8A%A0%E8%BD%BD/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/PHP/ - 2022-03-27 + https://nicksxs.me/categories/Linux/%E5%91%BD%E4%BB%A4/top/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/%E5%88%86%E5%B8%83%E5%BC%8F%E4%BA%8B%E5%8A%A1/%E4%B8%A4%E9%98%B6%E6%AE%B5%E6%8F%90%E4%BA%A4/ - 2022-03-27 + https://nicksxs.me/categories/Thread-dump/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97/ - 2022-03-27 + https://nicksxs.me/categories/Dubbo/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/%E7%94%9F%E6%B4%BB/%E5%90%90%E6%A7%BD/%E7%96%AB%E6%83%85/%E7%BE%8E%E5%9B%BD/ - 2022-03-27 + https://nicksxs.me/categories/Mysql/%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/%E7%94%9F%E6%B4%BB/%E5%90%90%E6%A7%BD/%E7%96%AB%E6%83%85/%E5%8F%A3%E7%BD%A9/ - 2022-03-27 + https://nicksxs.me/categories/Dubbo-%E7%BA%BF%E7%A8%8B%E6%B1%A0/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/%E5%B0%8F%E6%8A%80%E5%B7%A7/grep/ - 2022-03-27 + https://nicksxs.me/categories/Mysql/%E7%B4%A2%E5%BC%95/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/%E7%94%9F%E6%B4%BB/%E8%BF%90%E5%8A%A8/%E8%B7%91%E6%AD%A5/%E5%B9%B2%E6%B4%BB/ - 2022-03-27 + https://nicksxs.me/categories/Redis/%E5%BA%94%E7%94%A8/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/C/Redis/ - 2022-03-27 + https://nicksxs.me/categories/Mac/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Spring/Servlet/Interceptor/ - 2022-03-27 + https://nicksxs.me/categories/SpringBoot/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/MQ/RocketMQ/%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97/ - 2022-03-27 + https://nicksxs.me/categories/%E5%B0%8F%E6%8A%80%E5%B7%A7/top/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Docker/%E5%8F%91%E8%A1%8C%E7%89%88%E6%9C%AC/ - 2022-03-27 + https://nicksxs.me/categories/%E7%94%9F%E6%B4%BB/%E6%97%85%E6%B8%B8/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Dubbo/SPI/ - 2022-03-27 + https://nicksxs.me/categories/%E9%97%AE%E9%A2%98%E6%8E%92%E6%9F%A5/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Dubbo/%E5%AE%B9%E9%94%99%E6%9C%BA%E5%88%B6/ - 2022-03-27 + https://nicksxs.me/categories/Dubbo/SPI/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Spring/Mybatis/ - 2022-03-27 + https://nicksxs.me/categories/%E5%88%86%E5%B8%83%E5%BC%8F%E4%BA%8B%E5%8A%A1/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/%E5%B0%8F%E6%8A%80%E5%B7%A7/top/ - 2022-03-27 + https://nicksxs.me/categories/Mysql/%E6%BA%90%E7%A0%81/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/%E5%B7%A5%E5%85%B7/ - 2022-03-27 + https://nicksxs.me/categories/Dubbo/%E7%BA%BF%E7%A8%8B%E6%B1%A0/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Mysql/%E6%BA%90%E7%A0%81/ - 2022-03-27 + https://nicksxs.me/categories/%E7%94%9F%E6%B4%BB/%E5%BC%80%E8%BD%A6/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Dubbo/%E7%BA%BF%E7%A8%8B%E6%B1%A0/ - 2022-03-27 + https://nicksxs.me/categories/Dubbo/%E5%AE%B9%E9%94%99%E6%9C%BA%E5%88%B6/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/%E7%BC%93%E5%AD%98/ - 2022-03-27 + https://nicksxs.me/categories/Java/Design-Patterns/ + 2022-04-02 weekly 0.2 https://nicksxs.me/categories/C/Mysql/ - 2022-03-27 + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Mac/Homebrew/ - 2022-03-27 + https://nicksxs.me/categories/Redis/%E7%BC%93%E5%AD%98/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/%E5%88%86%E5%B8%83%E5%BC%8F%E4%BA%8B%E5%8A%A1/%E4%B8%89%E9%98%B6%E6%AE%B5%E6%8F%90%E4%BA%A4/ - 2022-03-27 + https://nicksxs.me/categories/PHP/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97/RocketMQ/ - 2022-03-27 + https://nicksxs.me/categories/%E5%B0%8F%E6%8A%80%E5%B7%A7/top/%E6%8E%92%E5%BA%8F/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/%E5%B0%8F%E6%8A%80%E5%B7%A7/grep/%E6%9F%A5%E6%97%A5%E5%BF%97/ - 2022-03-27 + https://nicksxs.me/categories/%E5%B7%A5%E5%85%B7/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Spring/Servlet/Interceptor/AOP/ - 2022-03-27 + https://nicksxs.me/categories/Dubbo/SPI/Adaptive/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Dubbo/SPI/Adaptive/ - 2022-03-27 + https://nicksxs.me/categories/%E5%88%86%E5%B8%83%E5%BC%8F%E4%BA%8B%E5%8A%A1/%E4%B8%A4%E9%98%B6%E6%AE%B5%E6%8F%90%E4%BA%A4/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/%E5%B0%8F%E6%8A%80%E5%B7%A7/top/%E6%8E%92%E5%BA%8F/ - 2022-03-27 + https://nicksxs.me/categories/Dubbo/%E7%BA%BF%E7%A8%8B%E6%B1%A0/ThreadPool/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/Dubbo/%E7%BA%BF%E7%A8%8B%E6%B1%A0/ThreadPool/ - 2022-03-27 + https://nicksxs.me/categories/Java/Singleton/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/%E7%BC%93%E5%AD%98/%E7%A9%BF%E9%80%8F/ - 2022-03-27 + https://nicksxs.me/categories/%E7%BC%93%E5%AD%98/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/PHP/icu4c/ - 2022-03-27 + https://nicksxs.me/categories/Mac/Homebrew/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/%E4%B8%AD%E9%97%B4%E4%BB%B6/ - 2022-03-27 + https://nicksxs.me/categories/%E5%88%86%E5%B8%83%E5%BC%8F%E4%BA%8B%E5%8A%A1/%E4%B8%89%E9%98%B6%E6%AE%B5%E6%8F%90%E4%BA%A4/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/%E7%BC%93%E5%AD%98/%E7%A9%BF%E9%80%8F/%E5%87%BB%E7%A9%BF/ - 2022-03-27 + https://nicksxs.me/categories/%E7%BC%93%E5%AD%98/%E7%A9%BF%E9%80%8F/ + 2022-04-02 weekly 0.2 - https://nicksxs.me/categories/%E4%B8%AD%E9%97%B4%E4%BB%B6/RocketMQ/ - 2022-03-27 + https://nicksxs.me/categories/PHP/icu4c/ + 2022-04-02 + weekly + 0.2 + + + + https://nicksxs.me/categories/%E7%BC%93%E5%AD%98/%E7%A9%BF%E9%80%8F/%E5%87%BB%E7%A9%BF/ + 2022-04-02 weekly 0.2 https://nicksxs.me/categories/%E7%BC%93%E5%AD%98/%E7%A9%BF%E9%80%8F/%E5%87%BB%E7%A9%BF/%E9%9B%AA%E5%B4%A9/ - 2022-03-27 + 2022-04-02 weekly 0.2