<?xml version="1.0" encoding="utf-8" ?><rss version="2.0"><channel><title><![CDATA[ljcgit的博客]]></title><description><![CDATA[]]></description><link>https://blog.youkuaiyun.com/ljcgit</link><language>zh-cn</language><generator>https://blog.youkuaiyun.com/</generator><copyright><![CDATA[Copyright &copy; ljcgit]]></copyright><item><title><![CDATA[Kafka源码系列(一)——源码环境搭建]]></title><link>https://blog.youkuaiyun.com/ljcgit/article/details/120823203</link><guid>https://blog.youkuaiyun.com/ljcgit/article/details/120823203</guid><author>ljcgit</author><pubDate>Mon, 18 Oct 2021 13:06:00 +0800</pubDate><description><![CDATA[这里使用的Kafka版本是**2.8.1**，差不多是最新的2.X.X版本，2021.9.21已经出了最新的3.0.0版本，该版本移除了Java 8以及Scala 2.12，在环境配置上有所不同，后续有时间会更新最新的3.0.0环境搭建内容。

操作系统：MAC

1. Java 设置
JDK版本是1.8，这里就不描述具体的操作步骤。
ljc:~ luojiacheng$ java -version
java version "1.8.0_221"
Java(TM) SE Runtime Environm.]]></description><category></category></item><item><title><![CDATA[MySQL 锁机制系列（一） —— Next-Key Lock]]></title><link>https://blog.youkuaiyun.com/ljcgit/article/details/120772413</link><guid>https://blog.youkuaiyun.com/ljcgit/article/details/120772413</guid><author>ljcgit</author><pubDate>Thu, 14 Oct 2021 20:54:23 +0800</pubDate><description><![CDATA[背景故事




事务A
事务B




begin;



select count(*) from t_user where uid &gt; 20;// 返回1




insert into t_user values(30,‘AA’,20);


update t_user set age = 30 where uid &gt; 20;// 显示有两条记录修改成功



上面两个事务，首先先开启事务A，查询id大于20的记录数，结果返回1，说明只有1条记录uid大于20，随后事务B插入了一条uid]]></description><category></category></item><item><title><![CDATA[细说ConcurrentHashMap扩容规则]]></title><link>https://blog.youkuaiyun.com/ljcgit/article/details/118933194</link><guid>https://blog.youkuaiyun.com/ljcgit/article/details/118933194</guid><author>ljcgit</author><pubDate>Tue, 20 Jul 2021 13:41:08 +0800</pubDate><description><![CDATA[当数组中存放的节点个数超过了阈值就可以任务当前的哈希冲突可能性较大，HashMap就会对当前数组进行扩容操作。在普通的HashMap中就会直接声明一个两倍大小的新数组，然后从旧数组中从左到右进行转化，但是在多线程下肯定会存在线程安全的问题。那么ConcurrentHashMap是如何来保证多线程下的扩容安全的呢？
transfer是进行扩容操作的方法，接收两个参数tab（原容器数组对象），nextTab（新容器数组对象，一般长度为tab的两倍）。
private final void transfer(No]]></description><category></category></item><item><title><![CDATA[细说ConcurrentHashMap计数规则]]></title><link>https://blog.youkuaiyun.com/ljcgit/article/details/118802810</link><guid>https://blog.youkuaiyun.com/ljcgit/article/details/118802810</guid><author>ljcgit</author><pubDate>Fri, 16 Jul 2021 15:45:28 +0800</pubDate><description><![CDATA[对于ConcurrentHashMap而言，需要保证的是任何操作的线程安全，包括对集合元素个数的统计。
一般在多线程下要统计一个全局数量大小，可以通过cas+循环（或者直接用Atomic相关的类）的方式实现，但是ConcurrentHashMap作者却并不是这样实现的。
先看看如何获取集合中的元素个数，通过调用size()方法：
public int size() {
    long n = sumCount();
    return ((n &lt; 0L) ? 0 :
            (n ]]></description><category></category></item><item><title><![CDATA[记一次Java参数传递时值发生变化问题]]></title><link>https://blog.youkuaiyun.com/ljcgit/article/details/118728825</link><guid>https://blog.youkuaiyun.com/ljcgit/article/details/118728825</guid><author>ljcgit</author><pubDate>Wed, 14 Jul 2021 15:28:42 +0800</pubDate><description><![CDATA[0.前景回顾
代码内容如下：
private boolean dfs(char[][] board, int[][] k, String word, int index, int i, int j) {
    if (index &gt;= word.length()) {
        return true;
    }
    if (i &gt;= board.length || i &lt; 0 || j &lt; 0 || j &gt;= board[0].length) {
       ]]></description><category></category></item><item><title><![CDATA[MySQL explain常见场景分析]]></title><link>https://blog.youkuaiyun.com/ljcgit/article/details/118600853</link><guid>https://blog.youkuaiyun.com/ljcgit/article/details/118600853</guid><author>ljcgit</author><pubDate>Fri, 09 Jul 2021 10:45:11 +0800</pubDate><description><![CDATA[实际场景分析：
建表语句：
CREATE TABLE `t` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `a` int(11) DEFAULT NULL,
  `b` int(11) DEFAULT NULL,
  `c` int(11) DEFAULT NULL,
  `d` varchar(20) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `uindex` (`a`,`b`,`c`)
) ENGINE=InnoDB ]]></description><category></category></item><item><title><![CDATA[leetcode 1206 设计跳表java实现]]></title><link>https://blog.youkuaiyun.com/ljcgit/article/details/118381368</link><guid>https://blog.youkuaiyun.com/ljcgit/article/details/118381368</guid><author>ljcgit</author><pubDate>Thu, 01 Jul 2021 10:49:06 +0800</pubDate><description><![CDATA[不使用任何库函数，设计一个跳表。
跳表是在 O(log(n)) 时间内完成增加、删除、搜索操作的数据结构。跳表相比于树堆与红黑树，其功能与性能相当，并且跳表的代码长度相较下更短，其设计思想与链表相似。
例如，一个跳表包含 [30, 40, 50, 60, 70, 90]，然后增加 80、45 到跳表中，以下图的方式操作：

Artyom Kalinin [CC BY-SA 3.0], via Wikimedia Commons
跳表中有很多层，每一层是一个短的链表。在第一层的作用下，增加、删除和搜索操作的时]]></description><category></category></item><item><title><![CDATA[记一次愚蠢的AOP使用经历]]></title><link>https://blog.youkuaiyun.com/ljcgit/article/details/117670240</link><guid>https://blog.youkuaiyun.com/ljcgit/article/details/117670240</guid><author>ljcgit</author><pubDate>Mon, 07 Jun 2021 18:09:52 +0800</pubDate><description><![CDATA[在写aop代码时，不知怎的出现了类似下面所写的愚蠢代码，将proceed方法放到了一个新线程。
    @Around("execution(* com.ljc.service.Doc.read())")
    public Object doBasicProfiling1(ProceedingJoinPoint pjp) throws Throwable {
        new Thread(() -&gt; {
            try {
                Object re]]></description><category></category></item><item><title><![CDATA[重识Spring的BeanPostProcessor处理器]]></title><link>https://blog.youkuaiyun.com/ljcgit/article/details/115904080</link><guid>https://blog.youkuaiyun.com/ljcgit/article/details/115904080</guid><author>ljcgit</author><pubDate>Tue, 20 Apr 2021 13:37:31 +0800</pubDate><description><![CDATA[重识Spring的BeanPostProcessor处理器
BeanPostProcessor是Spring用来实现快速拓展最为核心的接口，现在常说的AOP就是通过实现BeanPostProcessor接口来进行拓展。
下面就先看下BeanPostProcessor到底长什么样？????
BeanPostProcessor接口
public interface BeanPostProcessor {

	 //在bean init之前执行
   @Nullable
   default Object pos]]></description><category></category></item><item><title><![CDATA[Spring为什么需要使用三级缓存？]]></title><link>https://blog.youkuaiyun.com/ljcgit/article/details/115727194</link><guid>https://blog.youkuaiyun.com/ljcgit/article/details/115727194</guid><author>ljcgit</author><pubDate>Thu, 15 Apr 2021 15:29:13 +0800</pubDate><description><![CDATA[Spring为什么需要使用三级缓存？
有如下一个场景，X类中注入了Y类，Y类注入了X类，按照正常的类加载顺序，X类在注入Y的时候其实还没完全初始化完成，而注入的Y此时就开始实例化，发现也需要用到X，这是就去获取X，但是X并没有初始化完成，这个时候就会出现X在等Y初始化完成，而Y又在等X初始化完成，就进入了一个互相等待的情况。
Spring是如何避免这种情况的呢？那就是三级缓存。
先来说说Spring有哪三级缓存。

一级缓存 singletonObject  ： 单例对象集合；
二级缓存 earlySing]]></description><category></category></item><item><title><![CDATA[@Autowired 和 @Resource比较]]></title><link>https://blog.youkuaiyun.com/ljcgit/article/details/115368641</link><guid>https://blog.youkuaiyun.com/ljcgit/article/details/115368641</guid><author>ljcgit</author><pubDate>Thu, 01 Apr 2021 10:38:59 +0800</pubDate><description><![CDATA[@Autowired 和 @Resource比较
所属的包不同
@Autowired：org.springframework.beans.factory.annotation，即为Spring中的类；
@Resource：javax.annotation，属于jdk。
使用上
@Autowired和@Resource使用没什么区别，都可以作用在字段或者方法上；
@Autowired ：没有name和type属性，默认是注入方式是byType，当有多个类型匹配的bean时会抛出异常信息，问我借助于@Quali]]></description><category></category></item><item><title><![CDATA[@Autowired详解]]></title><link>https://blog.youkuaiyun.com/ljcgit/article/details/115361068</link><guid>https://blog.youkuaiyun.com/ljcgit/article/details/115361068</guid><author>ljcgit</author><pubDate>Wed, 31 Mar 2021 21:11:29 +0800</pubDate><description><![CDATA[@Autowired详解
@Autowired是在Spring中新引入的注解，所属的包为org.springframework.beans.factory.annotation;
定义如下：
@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER, ElementType.FIELD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME]]></description><category></category></item><item><title><![CDATA[@Resource详解]]></title><link>https://blog.youkuaiyun.com/ljcgit/article/details/115353149</link><guid>https://blog.youkuaiyun.com/ljcgit/article/details/115353149</guid><author>ljcgit</author><pubDate>Wed, 31 Mar 2021 16:14:57 +0800</pubDate><description><![CDATA[@Resource详解
阅读本文之前希望读者最好已经对整个Bean的大体Spring执行顺序已经有了一定的了解。
示例
定义一个接口，表示水果类，只包含一个方法代表售卖。
public interface Fruit {

    void sell();
}

有两个具体实现类，Apple????和Banana????。
@Service
public class Apple implements Fruit {


    public Apple() {
        System.out.prin]]></description><category></category></item><item><title><![CDATA[Spring 循环依赖]]></title><link>https://blog.youkuaiyun.com/ljcgit/article/details/115242381</link><guid>https://blog.youkuaiyun.com/ljcgit/article/details/115242381</guid><author>ljcgit</author><pubDate>Fri, 26 Mar 2021 14:23:32 +0800</pubDate><description><![CDATA[Spring —— 循环依赖
Spring Bean默认都是以单例的形式存在，但是也支持prototype形式，这里主要介绍单例Bean。
示例
@Component
public class X {

    @Autowired
    private Y y;

    public X() {
        System.out.println("X construct...");
    }
}

@Component
public class Y {

    @Autowired
    p]]></description><category></category></item><item><title><![CDATA[Spring Bean的完整生命周期回调]]></title><link>https://blog.youkuaiyun.com/ljcgit/article/details/115208357</link><guid>https://blog.youkuaiyun.com/ljcgit/article/details/115208357</guid><author>ljcgit</author><pubDate>Thu, 25 Mar 2021 14:40:38 +0800</pubDate><description><![CDATA[Bean的生命周期回调
​     Bean的生命周期回调主要是在Bean对象创建和销毁的过程中会执行一些init和destroy方法，了解不同形式的init和destroy声明方法，以及它们之间的先后执行顺序会有助于我们理解Bean的生命周期过程。下文主要介绍了生命周期回调的各种使用方式，以及在Spring中是如何实现的。
常用的三种形式：

InitializingBean 和DisposableBean接口，分别实现afterPropertiesSet 和 destroy方法；
JSR-250下的@P]]></description><category></category></item><item><title><![CDATA[Java获取静态资源文件路径]]></title><link>https://blog.youkuaiyun.com/ljcgit/article/details/112897230</link><guid>https://blog.youkuaiyun.com/ljcgit/article/details/112897230</guid><author>ljcgit</author><pubDate>Wed, 20 Jan 2021 17:02:40 +0800</pubDate><description><![CDATA[Java获取静态资源文件路径
​		开发中经常会有文件相关的操作，比如说文件的查找，文件的存储。但是在使用中往往会因为路径问题耽误大量的开发时间。在实际中常常通过File file = new File(“c://a.txt”)方式来使用，但是切换环境后可能会遇到找不到该资源的问题。Java中，可以使用getResource()方法来获取资源。
项目工程如下：

![目录结构](https://img-blog.csdnimg.cn/20210120170130893.png?x-oss-process=i]]></description><category></category></item><item><title><![CDATA[记一次RestTemplate使用异常问题]]></title><link>https://blog.youkuaiyun.com/ljcgit/article/details/108849531</link><guid>https://blog.youkuaiyun.com/ljcgit/article/details/108849531</guid><author>ljcgit</author><pubDate>Mon, 28 Sep 2020 15:05:01 +0800</pubDate><description><![CDATA[场景描述

系统需要调用第三方的http接口，并获取到返回的json格式结果。



问题

用RestTemplate进行GET形式调用时发现和浏览器直接访问效果不同，可能无法访问接口，或者参数存在问题导致请求返回异常结果。

调用格式如下：



String result = restTemplate.getForObject("http://127.0.0.1:8080/acm?k=%3", String.class);



解决

接口调用出现异常，马上就想到了请求格式发生了变化，通过调试模式.]]></description><category></category></item><item><title><![CDATA[分布式]]></title><link>https://blog.youkuaiyun.com/ljcgit/article/details/107658441</link><guid>https://blog.youkuaiyun.com/ljcgit/article/details/107658441</guid><author>ljcgit</author><pubDate>Wed, 29 Jul 2020 11:01:09 +0800</pubDate><description><![CDATA[1. 2PC
1.1 准备阶段

事务协调者向所有参与者节点询问是否可以执行提交操作，并开始等待各参与者节点的响应。
参与者节点执行询问发起为止的所有事务操作，并将Undo和Redo信息写入日志。
各参与者节点响应事务协调者发起的询问。如果参与者节点的事务操作实际执行成功，则它返回一个“同意”信息，否则返回“终止”信息。

1.2 提交阶段
所有参与者节点都返回同意

事务协调者节点向所有参与者节点发出“正式提交”的请求。
参与者节点正式完成操作，并释放在整个事务期间内占用的资源。
参与者节点向协调者节点发]]></description><category></category></item><item><title><![CDATA[Redis笔记]]></title><link>https://blog.youkuaiyun.com/ljcgit/article/details/107658386</link><guid>https://blog.youkuaiyun.com/ljcgit/article/details/107658386</guid><author>ljcgit</author><pubDate>Wed, 29 Jul 2020 10:59:42 +0800</pubDate><description><![CDATA[Redis五大数据类型及其常用操作
字符串
set key value ——设置属性值
get key ——获取值
getset key value   ——先获取值再重新设置值
del key ——删除
incr key  ——自增，如果key不存在，则会创建一个值为0的变量
decr key ——自减
incrby key number ——变量+number
decrby key number ——变量-number
append key string ——追加字符串
getrange key sta]]></description><category></category></item><item><title><![CDATA[netty知识点（一）]]></title><link>https://blog.youkuaiyun.com/ljcgit/article/details/107658298</link><guid>https://blog.youkuaiyun.com/ljcgit/article/details/107658298</guid><author>ljcgit</author><pubDate>Wed, 29 Jul 2020 10:57:45 +0800</pubDate><description><![CDATA[1. rmi（remote method invocation）

只针对java

client：stud 桩
server：skeleton 骨架
2. RPC（Remote Procedure Call）远程过程调用

跨语言


定义一个接口说明文件：描述了对象（结构体）、对象成员、接口方法等一系列信息。
通过RPC框架所提供的编译器，将接口说明文件编译成具体语言文件。
在客户端与服务器端分别使用RPC编译器所生成的文件，即可像调用本地方法一样调用远程方法。


相对于Rest形式可以减少网络传输。]]></description><category></category></item></channel></rss>