<?xml version="1.0" encoding="utf-8" ?><rss version="2.0"><channel><title><![CDATA[程序袁小黑]]></title><description><![CDATA[迷茫了太久，想往深了做几件事]]></description><link>https://blog.csdn.net/ydonghao2</link><language>zh-cn</language><generator>https://blog.csdn.net/</generator><copyright><![CDATA[Copyright &copy; ydonghao2]]></copyright><item><title><![CDATA[同事面试遇到的奇怪问题]]></title><link>https://blog.csdn.net/ydonghao2/article/details/109994392</link><guid>https://blog.csdn.net/ydonghao2/article/details/109994392</guid><author>ydonghao2</author><pubDate>Mon, 23 Nov 2020 14:04:30 +0800</pubDate><description><![CDATA[    近日同事面试资深Java开发工程师在回到MySql索引的时候，遇到了个奇怪的问题：为什么有最左匹配原则？
    其实我理解遇到这个问题有可能是面试官对前面的回答不是很满意，随口问了句这种话，毕竟这种话问出来有点为难的意思。
    然后我们拿这个问题来讨论下，真是八仙过海，谁都有谁的答案，谁都不服谁。也许这就是程序员吧。
    下面是我的个人理解，如果读者有更好的想法，欢迎回复加入讨论。
B+树的结构

    从上面可以看出来B+树的索引结构。
    其实根节点只存建索引的数据段。真正的da]]></description><category></category></item><item><title><![CDATA[不一样的CAP，拒绝网上抄抄抄]]></title><link>https://blog.csdn.net/ydonghao2/article/details/109670218</link><guid>https://blog.csdn.net/ydonghao2/article/details/109670218</guid><author>ydonghao2</author><pubDate>Fri, 13 Nov 2020 10:46:15 +0800</pubDate><description><![CDATA[不一样的CAP，拒绝网上抄抄抄

接触CAP和BASE理论很久了，也看了很多资料，每次看了之后都觉得不对劲，网上绝大多数资料包括很多书中就会copy来copy去（能有点出息不）。
看了之后脑子里面疑问：CAP，BASE和我们平时的应用有什么关系？ 倒是落个地呀，举几个例子给我看看呀。哎，还是我自己总结算了。
以下内容都是我个人的理解，如果大家有什么不同的意见欢迎一起探讨。

开篇复习CAP理论的文字定义
CAP英文：帽子，其实和帽子一点关系都没有，是三个单词的首字母和一起得出的CAP。三个字母分别是：
C：]]></description><category></category></item><item><title><![CDATA[Swagger为什么不使用注释做接口描述]]></title><link>https://blog.csdn.net/ydonghao2/article/details/109593416</link><guid>https://blog.csdn.net/ydonghao2/article/details/109593416</guid><author>ydonghao2</author><pubDate>Tue, 10 Nov 2020 10:17:46 +0800</pubDate><description><![CDATA[背景
使用Swagger的时候有一种痛苦，侵入性太强了。我个人又喜欢写注释，我理解注释写得越好，越能减少沟通的交流，节省人力，提高工作效率。所以想着使用Controller的注释和实体的注释，就能替换Swagger的***注解***。全网找下来，有实现这个功能的：github，但是我使用之后发现一些bug联系不上作者，而且我不会Kotlin， 所以还是需要自己研究一下。
设计
pom文件依赖
因为考虑想开源给大家使用，这里没有去依赖顶层的pom文件。
研究swagger的源码
通过研究swagger的源码发]]></description><category></category></item><item><title><![CDATA[总结每天之上下文切换]]></title><link>https://blog.csdn.net/ydonghao2/article/details/109507171</link><guid>https://blog.csdn.net/ydonghao2/article/details/109507171</guid><author>ydonghao2</author><pubDate>Thu, 05 Nov 2020 10:49:16 +0800</pubDate><description><![CDATA[16、什么是上下文切换
答：
比如人工作的时候，准备好装备好工作需要的工具才能开始正常工作，否则都是工作的准备阶段。而我们的cpu是分片执行的（因为CPU运行速度太快，不想浪费，所以都是分片运行任务），我们一般的操作系统都是多任务系统，需要执行其它任务，那么就需要把当前任务的工作环境也就是运行环境保存到内存里，然后把下一个任务的工作环境/运行环境（其实就是寄存器、程序计数器那些东西就绪）放入CPU中，然后开始执行。
这两个任务运行环境切换称为上下文切换。
17、上下文切换的过程
答：
1）挂起一个进程，将这]]></description><category></category></item><item><title><![CDATA[Java后台线程/守护线程/服务线程]]></title><link>https://blog.csdn.net/ydonghao2/article/details/109494924</link><guid>https://blog.csdn.net/ydonghao2/article/details/109494924</guid><author>ydonghao2</author><pubDate>Wed, 04 Nov 2020 17:24:09 +0800</pubDate><description><![CDATA[Thread.setDaemon(true)开启守护线程，守护线程就是在后台运行的线程，它会随着父线程结束而结束。 Daemon 线程中产生的新线程也是 Daemon 的。当 JVM 中所有的线程都是守护线程的时候， JVM 就可以退出了；如果还有一个或以上的非守护线程则 JVM 不会退出。
可以看下面的代码：
public class DaemonThreadTest {
    public static void main(String[] args) {
        new Thread(()-]]></description><category></category></item><item><title><![CDATA[带圆圈的数字和markdown常用表达式记录]]></title><link>https://blog.csdn.net/ydonghao2/article/details/109494230</link><guid>https://blog.csdn.net/ydonghao2/article/details/109494230</guid><author>ydonghao2</author><pubDate>Wed, 04 Nov 2020 17:04:05 +0800</pubDate><description><![CDATA[上波浪线:
$\widetilde{\phi}$

&nbsp;ϕ~~ \widetilde{\phi}&nbsp;ϕ​
​
带圆圈的数字：
⓪ ① ② ③ ④ ⑤ ⑥ ⑦ ⑧ ⑨ ⑩ ⑪ ⑫ ⑬ ⑭ ⑮ ⑯ ⑰ ⑱ ⑲ ⑳ ㉑ ㉒ ㉓ ㉔ ㉕ ㉖ ㉗ ㉘ ㉙ ㉚ ㉛ ㉜ ㉝ ㉞ ㉟ ㊱ ㊲ ㊳ ㊴ ㊵ ㊶ ㊷ ㊸ ㊹ ㊺ ㊻ ㊼ ㊽ ㊾ ㊿
These are specifically sans-serif:
???? ➀ ➁ ➂ ➃ ➄ ➅ ➆ ➇ ➈ ➉
Black Circled Number
⓿ ]]></description><category></category></item><item><title><![CDATA[有三个线程怎么保证顺序性]]></title><link>https://blog.csdn.net/ydonghao2/article/details/109492640</link><guid>https://blog.csdn.net/ydonghao2/article/details/109492640</guid><author>ydonghao2</author><pubDate>Wed, 04 Nov 2020 16:07:54 +0800</pubDate><description><![CDATA[保证顺序性其实就是java多线程通信的问题。三个线程协定执行的先后顺序，转换成线程通信的问题，我需要用一个东西来协定执行到哪个线程了，这东西实现方式就有很多了：
Java的线程通信都是使用内存共享变量的方式，那么就简单的方式就是：

一个共享变量。这个共享变量可以是一个简单的静态变量，可以是一个Semaphore等。

其实如果考虑抢锁会消耗性能，如果我不跑的线程进行挂起呢？
实现方式2
2）线程的wait和notify
如果对底层了解一点，我个人理解性能最高的方式其实是直接使用LockSupport.pa]]></description><category></category></item><item><title><![CDATA[因为多线程，我怼了一个同事]]></title><link>https://blog.csdn.net/ydonghao2/article/details/109491352</link><guid>https://blog.csdn.net/ydonghao2/article/details/109491352</guid><author>ydonghao2</author><pubDate>Wed, 04 Nov 2020 15:26:25 +0800</pubDate><description><![CDATA[背景：
今天同事在看我写锁同步的总结，兴致来了想考考我，问我synchronized 保证变量的可见性吗？
我回答可以，他的答案是synchronized不保证可见性，volatile才保证可见性。结果两人起来争执，为此他特意写了如下代码来证明他说的是正确的：
重点戏
/**
 * 证明，synchronized能不能保重对象可见性。
 */
public class SynchronizedLock {

    private static int count = 0;

    public void]]></description><category></category></item><item><title><![CDATA[总结每天10问之java多线程1]]></title><link>https://blog.csdn.net/ydonghao2/article/details/109489919</link><guid>https://blog.csdn.net/ydonghao2/article/details/109489919</guid><author>ydonghao2</author><pubDate>Wed, 04 Nov 2020 14:36:03 +0800</pubDate><description><![CDATA[Java 多线程
1、Java中实现多线程有多少种方式：
答：

继承Thread；

2）实现接口Runnable；
3）FutureTask
4）线程池
2、sleep()和wait() 有什么区别？
答：
sleep不会释放对象锁，wait会释放对象锁。
sleep会自我唤醒，wait需要notify/notifyAll。
3、volatile是什么？可以保存有序性吗？
答：
volatile是Java多线程解决可见性的问题提供的一个保留关键字，使用它可以保证多线程访问时该变量的可见性。可以保证部分有]]></description><category></category></item><item><title><![CDATA[总结每天10问之序列化]]></title><link>https://blog.csdn.net/ydonghao2/article/details/109453888</link><guid>https://blog.csdn.net/ydonghao2/article/details/109453888</guid><author>ydonghao2</author><pubDate>Mon, 02 Nov 2020 17:41:24 +0800</pubDate><description><![CDATA[1、什么是序列化？
答：
序列化我的理解是我们看到的数据转化成二进制bytes流向磁盘，网络。并经过磁盘、网络之后另外个时间点/另外一个操作系统进行反序列化，将二进制的bytes流翻译成我们能理解的数据格式；比如：json格式。
上面是大白话的回答：
下面是官方回答：
序列化就是一种用来处理对象流的机制，所谓对象流也就是将对象的内容进行流化。可以对流化后的对象进行读写操作，也可将流化后的对象传输于网络之间。序列化是为了解决在对对象流进行读写操作时所引发的问题。
序列化不仅仅局限于语言，而是网络、操作系统方面]]></description><category></category></item><item><title><![CDATA[总结每天10问之Java基础3]]></title><link>https://blog.csdn.net/ydonghao2/article/details/109432281</link><guid>https://blog.csdn.net/ydonghao2/article/details/109432281</guid><author>ydonghao2</author><pubDate>Sun, 01 Nov 2020 18:02:24 +0800</pubDate><description><![CDATA[Java 基础
OOP相关
21、讲讲类的实例化顺序？
答：


执行clinit方法
什么是clinit得等到jvm篇讲解的时候讲方便点，这里就记住clinit是class的static 变量，final变量，static代码块这些就好。clinit方法不是每个class都有的，Object就没有。
包括两个步骤：
1）执行父类的clinit方法。
2）执行子类的clinit方法。
clinit里面具体的执行逻辑是：
① 执行static filed
②执行static 代码块


执行init方法（构造]]></description><category></category></item><item><title><![CDATA[总结每天10问之Java基础2]]></title><link>https://blog.csdn.net/ydonghao2/article/details/109365122</link><guid>https://blog.csdn.net/ydonghao2/article/details/109365122</guid><author>ydonghao2</author><pubDate>Thu, 29 Oct 2020 17:34:53 +0800</pubDate><description><![CDATA[Java 基础
OOP相关
11、什么是拆装箱？
答：
在理解拆箱和装箱之前需要理解一个概念：基本类型和封装类型，比如int是基本类型，integer是封装类型（包装器类型）。
基本类型其实对应到c++或者直接说内存中的某个数据具体样子。int比integer占的内存小的多，integer的功能比int多得多。
这两者之间jdk为我们提供了一些转换的方式：拆装箱。
这是jdk5之后提供的，为的就是让基本类型和jdk封装类型之间能自动转换。这种自动转换也叫自动拆装箱。
在Java SE5之前，如果要生成一个数]]></description><category></category></item><item><title><![CDATA[总结每天10问之Java基础1]]></title><link>https://blog.csdn.net/ydonghao2/article/details/109364124</link><guid>https://blog.csdn.net/ydonghao2/article/details/109364124</guid><author>ydonghao2</author><pubDate>Thu, 29 Oct 2020 16:59:35 +0800</pubDate><description><![CDATA[Java 基础
OOP相关
1、什么是B/S架构？什么是C/S架构
答：
B/S中B是Brower，浏览器的意思；S是Server，即Brower/Server，用户通过浏览器访问服务。
C/S中C是Client，客户端的意思；Client的范围很大，可以包括浏览器，但是一般情况都是桌面定制。
2、Java都有那些开发平台？
答：
1）Java SE：主要用在客户端开发
2）Java EE：主要用在Wef服务器开发
3）Java ME：主要用在嵌入式开发
3、JDK和JRE的区别
答：
1）JDK：Java]]></description><category></category></item><item><title><![CDATA[RocketMQ压测报告书]]></title><link>https://blog.csdn.net/ydonghao2/article/details/109268031</link><guid>https://blog.csdn.net/ydonghao2/article/details/109268031</guid><author>ydonghao2</author><pubDate>Sat, 24 Oct 2020 23:26:41 +0800</pubDate><description><![CDATA[RocketMQ压测报告书

公司需要压测RocketMq，这里给出个人的压测结果。因为机器不足的原因，这里只能做基准测试。不能做容量测试、稳定性和异常测试。

1. 部署结构
1.1 机器组成
2台机器 4c16g nameserver
4台机器 4c16g broker
压力机一台 一个 producer + 一个consumer
1.2 OS配置
系统：Linux ，CentOs7
内核：Linux version 4.4.238-1.el7.elrepo.x86_64，（CentOS7默认使用的是3]]></description><category></category></item><item><title><![CDATA[ThreadLocal原理解析]]></title><link>https://blog.csdn.net/ydonghao2/article/details/107453527</link><guid>https://blog.csdn.net/ydonghao2/article/details/107453527</guid><author>ydonghao2</author><pubDate>Sun, 19 Jul 2020 22:59:04 +0800</pubDate><description><![CDATA[个人理解ThreadLocal的原理得结合Thread和ThradGroup体系才能解释清楚。这是一个自底向上的讲解，所以请各位耐心看到最后，才能明白ThreadLocal的原理。
关于ThreadGroup和Thread源码的分析，请看我前面的文章。
Thread之中有如下两个属性：
public class Thread implements Runnable {
    /* ThreadLocal values pertainingz(有关) to this thread. This map is ]]></description><category></category></item><item><title><![CDATA[Thread源码解析]]></title><link>https://blog.csdn.net/ydonghao2/article/details/107453376</link><guid>https://blog.csdn.net/ydonghao2/article/details/107453376</guid><author>ydonghao2</author><pubDate>Sun, 19 Jul 2020 22:56:11 +0800</pubDate><description><![CDATA[多线程编程一直是业界公认比较难也是比较重要，而且是非常基础的一点，掌握它非常重要。Java中多线程编程比较幸福，因为Jdk工程师们考虑了很多东西尽量减少使用Java的难度和复杂度。其实在C++之中是没有内建多线程的，它依赖操作系统提供这个特性，因为C++为了效率，控制C++适用的应用程序的范围。即C++没有内建多线程，它允许你直接使用操作系统提供的多线程。这也意味着你在Linux系统下编写的C++多线程代码很有可能在Windows下不能运行，这也是架构师技术选型的时候一个重要考虑点。

这边文章不是针对整.]]></description><category></category></item><item><title><![CDATA[ThreadGroup源码解析]]></title><link>https://blog.csdn.net/ydonghao2/article/details/107453352</link><guid>https://blog.csdn.net/ydonghao2/article/details/107453352</guid><author>ydonghao2</author><pubDate>Sun, 19 Jul 2020 22:46:56 +0800</pubDate><description><![CDATA[ThreadGroup 是对Java对Thread的一种组织方式。每一个ThreadGroup都是Thread的集合。
ThreadGroup是一个以树状结构维护的一个数据结构。再我们虚拟机一开始启动的时候就初始化一个Root ThreadGroup给我们，所有的线程都在这Root ThreadGroup下面。
ThreadGroup重要的属性如下：
public class ThreadGroup implements Thread.UncaughtExceptionHandler {
    /**
 ]]></description><category></category></item><item><title><![CDATA[Jdk之中的二分查找法]]></title><link>https://blog.csdn.net/ydonghao2/article/details/107394675</link><guid>https://blog.csdn.net/ydonghao2/article/details/107394675</guid><author>ydonghao2</author><pubDate>Thu, 16 Jul 2020 21:43:56 +0800</pubDate><description><![CDATA[闲逛看代码，看到了JDK之中实现的二分查找法。这里做一下介绍：

直接看源码
/**
     * Searches the specified list for the specified object using the binary
     * search algorithm.  The list must be sorted into ascending order
     * according to the specified comparator (as by the
     * {.]]></description><category></category></item><item><title><![CDATA[Spring扫描Jar包小用]]></title><link>https://blog.csdn.net/ydonghao2/article/details/107393301</link><guid>https://blog.csdn.net/ydonghao2/article/details/107393301</guid><author>ydonghao2</author><pubDate>Thu, 16 Jul 2020 20:52:02 +0800</pubDate><description><![CDATA[近来被委派了一个改造canal-adapter的工作，如果有机会就给大家介绍一下canal。遇到一个问题：class.getClassLoader.getResource()在打成jar的时候获取不到资源。

百度了一下，得到很多结果：
Java代码打成jar后 classgetClassLoadergetResource()返回为null
Java读取jar包中的文件（与从工程中拿文件不同，不能用new File形式）
各种劝我使用getResourceAsStream来获取文件。其实如果只是单单读一个.]]></description><category></category></item><item><title><![CDATA[Spring的钩子方法知多少]]></title><link>https://blog.csdn.net/ydonghao2/article/details/107168737</link><guid>https://blog.csdn.net/ydonghao2/article/details/107168737</guid><author>ydonghao2</author><pubDate>Mon, 06 Jul 2020 21:47:59 +0800</pubDate><description><![CDATA[Spring是我们经常使用的一个框架，它功能之一是提供了我们管理bean对象的手段，而且它提供了很多钩子方法给我们使用。什么是钩子方法呢？钩子方法就是：在bean的生命周期之中，经历了一系列的过程之中，Spring留给我们的一个后门，让我们能在Spring的生命周期之中执行我们想要的方法，从而实现我们想要的功能。接下来我们介绍一下生命周期，然后一个一个介绍我见过的样例或者我自己写的样例。

Spring生命周期的各种Aware
Spring的生命周期（我们撇开网络上很多资料，因为我觉得网络上很多资料要么不.]]></description><category></category></item></channel></rss>