<?xml version="1.0" encoding="utf-8" ?><rss version="2.0"><channel><title><![CDATA[gcfffff的博客]]></title><description><![CDATA[]]></description><link>https://blog.youkuaiyun.com/gcfffff</link><language>zh-cn</language><generator>https://blog.youkuaiyun.com/</generator><copyright><![CDATA[Copyright &copy; gcfffff]]></copyright><item><title><![CDATA[回调函数的使用]]></title><link>https://blog.youkuaiyun.com/gcfffff/article/details/138338257</link><guid>https://blog.youkuaiyun.com/gcfffff/article/details/138338257</guid><author>gcfffff</author><pubDate>Tue, 30 Apr 2024 10:43:52 +0800</pubDate><description><![CDATA[回调函数是一种将函数作为参数传递给另一个函数的方法。在这个例子中，我们创建了一个实现了Callback接口的匿名内部类，并将其传递给Caller类的构造函数。当doSomething方法执行完毕后，它会调用我们传递给它的回调函数。在这个类中，我们定义了一个名为doSomething的方法。这个方法在执行一些操作后，会调用回调接口的onCallback方法。在Java中，我们可以通过接口和实现接口的类来实现回调函数。这个接口定义了一个名为onCallback的方法，该方法接受一个字符串作为参数。]]></description><category></category></item><item><title><![CDATA[controller中路径为什么不能一致]]></title><link>https://blog.youkuaiyun.com/gcfffff/article/details/137646190</link><guid>https://blog.youkuaiyun.com/gcfffff/article/details/137646190</guid><author>gcfffff</author><pubDate>Thu, 11 Apr 2024 17:28:24 +0800</pubDate><description><![CDATA[非常简单的小问题路径一致报错。]]></description><category></category></item><item><title><![CDATA[MVCC的一些了解记录]]></title><link>https://blog.youkuaiyun.com/gcfffff/article/details/137234323</link><guid>https://blog.youkuaiyun.com/gcfffff/article/details/137234323</guid><author>gcfffff</author><pubDate>Mon, 01 Apr 2024 20:23:42 +0800</pubDate><description><![CDATA[MVCC（Multi-Version Concurrency Control）是多版本并发控制，以乐观锁为理论基础。通过对数据行的多个版本管理来实现数据库的并发控制。这样我们就可以通过比较版本号决定数据是否显示出来，读取数据的时候不需要加锁也可以保证事务的隔离效果，以此提高数据库并发性能。MVCC 没有固定的实现规范，不同数据库一般会有不同的实现方式。MySQL 中 InnoDB 采用了 MVCC 来实现“读已提交“和“可重复读”两个隔离级别。]]></description><category></category></item><item><title><![CDATA[java密码锁定逻辑]]></title><link>https://blog.youkuaiyun.com/gcfffff/article/details/137208699</link><guid>https://blog.youkuaiyun.com/gcfffff/article/details/137208699</guid><author>gcfffff</author><pubDate>Sun, 31 Mar 2024 20:46:21 +0800</pubDate><description><![CDATA[分享一下我在项目里写的密码锁定逻辑，目前在项目里的密码锁定逻辑是这样的，在五分钟内输错五次，就锁定三十分钟。很简单的一个小分享，用到了redis。]]></description><category></category></item><item><title><![CDATA[聊一下数据库事务(最近被高频面试）]]></title><link>https://blog.youkuaiyun.com/gcfffff/article/details/137201588</link><guid>https://blog.youkuaiyun.com/gcfffff/article/details/137201588</guid><author>gcfffff</author><pubDate>Sun, 31 Mar 2024 17:46:52 +0800</pubDate><description><![CDATA[要去完全认识数据库事务，得先了解什么是事务事务（Transaction）指一个操作，由多个步骤组成，要么全部成功，要么全部失败。举一个简单的例子：比如转账功能，A账户需要给B账户转账，需要进行下面两步：从 A 账户扣钱。往 B 账户加入等量的钱。因为是独立的两个操作，所以可能有一个成功，一个失败的情况。但是因为在这种场景下，不能存在从 A 账户扣钱成功，往 B 账户加入等量钱失败这种情况，要么同时成功，要么同时失败（一个失败需要回滚），即必须要保证事务。]]></description><category></category></item><item><title><![CDATA[列表for循环之再思考-CopyOnWriteList]]></title><link>https://blog.youkuaiyun.com/gcfffff/article/details/137140200</link><guid>https://blog.youkuaiyun.com/gcfffff/article/details/137140200</guid><author>gcfffff</author><pubDate>Fri, 29 Mar 2024 14:55:49 +0800</pubDate><description><![CDATA[接收一个要搜索的元素 o，当前的数组 elements，搜索的起始索引 index，以及搜索范围的结束索引 fence。它遍历从 index 到 fence（不包括 fence）的数组元素，如果找到与 e 相等的元素，则返回该元素的索引；我们能够发现，这块代码并没有对modCount的改动，核心就是通过复制了一份新的数组，再进行赋值操作（此处跳过需要删除的元素）,因此迭代器部分初始exceptModCount也是被赋值为modCount的0，迭代器对复制出来的删除元素并不感知，因此不会报错。]]></description><category></category></item><item><title><![CDATA[为什么不推荐使用redis的setnx进行分布式加锁]]></title><link>https://blog.youkuaiyun.com/gcfffff/article/details/137116803</link><guid>https://blog.youkuaiyun.com/gcfffff/article/details/137116803</guid><author>gcfffff</author><pubDate>Thu, 28 Mar 2024 19:32:34 +0800</pubDate><description><![CDATA[缺乏原子性：分布式锁的核心要求是原子性，即加锁和设置锁的过期时间应该是原子操作。然而，SETNX 命令只负责设置键的值，而不支持同时设置过期时间。这意味着你需要先调用 SETNX，然后再调用 EXPIRE 来设置锁的过期时间。这两个操作不是原子的，因此在它们之间可能发生一些导致不一致的情况，比如客户端在设置过期时间之前崩溃，导致锁永远不会被释放。锁释放的安全性问题：释放锁时，需要确保只有持有锁的客户端才能成功释放。]]></description><category></category></item><item><title><![CDATA[list的for循环中调用增删操作所带来的的思考]]></title><link>https://blog.youkuaiyun.com/gcfffff/article/details/137083859</link><guid>https://blog.youkuaiyun.com/gcfffff/article/details/137083859</guid><author>gcfffff</author><pubDate>Wed, 27 Mar 2024 19:13:06 +0800</pubDate><description><![CDATA[首先我们来看这段代码//迭代器我们发现这次会报这个错误at javaat com那我们如果用for循环呢同样的报错at javaat com那如果是普通for循环呢i++) {运行正常那如果是迭代器删除呢//迭代器同样没有报错接下来我们从底层代码分析我们最后总结一下，其实就是迭代器并不知道你进行了删除操作，所以我期望的改变值不等于改变值，java认为此时是不安全的，就会快速失败。而用迭代器自己的方法，就会保证迭代器知道我们每次改变的次数。]]></description><category></category></item><item><title><![CDATA[扫码登录方案实现]]></title><link>https://blog.youkuaiyun.com/gcfffff/article/details/137081814</link><guid>https://blog.youkuaiyun.com/gcfffff/article/details/137081814</guid><author>gcfffff</author><pubDate>Wed, 27 Mar 2024 16:40:43 +0800</pubDate><description><![CDATA[如果用户选择确认登录，APP 端校验 id 状态为已查询，则将 id 和 APP 端 token 发送到后端，后端根据 id 将 token。在 WEB 端点击二维码登录生成一个唯一 id 存储到 Redis，并且 给这个 id 设置为未被查询状态 0，根据此 id 生成二维码。APP 端进行扫码，获取到这个 id，查看 id 状态是否正常（如果 正常则将 id 状态修改为已查询；后端接收到登录请求，发现此 id 已有 token 时，根据此 app 的 token 所对用的用户重新生成新的 web 端。]]></description><category></category></item><item><title><![CDATA[jvm命令]]></title><link>https://blog.youkuaiyun.com/gcfffff/article/details/137043898</link><guid>https://blog.youkuaiyun.com/gcfffff/article/details/137043898</guid><author>gcfffff</author><pubDate>Tue, 26 Mar 2024 13:49:23 +0800</pubDate><description><![CDATA[承接上一篇，这块是我最近记录的jvm命令相关的。]]></description><category></category></item><item><title><![CDATA[JVM的一些小记]]></title><link>https://blog.youkuaiyun.com/gcfffff/article/details/137041720</link><guid>https://blog.youkuaiyun.com/gcfffff/article/details/137041720</guid><author>gcfffff</author><pubDate>Tue, 26 Mar 2024 12:00:12 +0800</pubDate><description><![CDATA[cpu处理数据的时候，会先从一级缓存去取，如果没有就从二级缓存中找，在没有就从三级缓存，还没有，那么就从内存中读取，但是不会只单单读取需要处理的数据，而是会读取一个64字节的块，因为CPU认为处理完这个数据大概率也会处理他相邻的数据，而这个块就是cache line。]]></description><category></category></item><item><title><![CDATA[hashmap jdk1.7头插法造成死循环的原因分析]]></title><link>https://blog.youkuaiyun.com/gcfffff/article/details/137034808</link><guid>https://blog.youkuaiyun.com/gcfffff/article/details/137034808</guid><author>gcfffff</author><pubDate>Tue, 26 Mar 2024 10:32:47 +0800</pubDate><description><![CDATA[好，现在线程1开始继续执行，上边已经说过，线程1在挂起之前已经取到了e节点（就是A节点），e.next就是B，只不过此时的B节点已经被线程2修改过了，B节点此时已经指向了A（即B节点的e.next不再是NULL，而是A节点）当然，数组扩展后会重新进行hash，节点A和B不一定还会挂在同一个链表上，我们为了分析问题，假设两个节点重新hash后，还在同一个链表上，就假设在3号位，这些都不重要。当再有线程3来扩容时，因为有环状链表，所以就会一直循环取节点，造成死循环。这时候线程1挂起，线程2继续执行。]]></description><category></category></item><item><title><![CDATA[hashmap中put和putVal方法]]></title><link>https://blog.youkuaiyun.com/gcfffff/article/details/137014981</link><guid>https://blog.youkuaiyun.com/gcfffff/article/details/137014981</guid><author>gcfffff</author><pubDate>Mon, 25 Mar 2024 15:12:27 +0800</pubDate><description><![CDATA[文章目录前言一、HashMap的重要属性二、put和putVal方法三、数组下标的计算方式总结前言我想只要JAVA程序员，都躲不过HashMap这一关，面试官的HashMap夺命连环问经常把求职者虐的体无完肤。因此，本篇文章以JDK8为例，对HashMap的底层源码做一个解析，帮助大家更好的理解HashMap的底层原理。一、HashMap的重要属性我想大家都应该知道在JDK8中HashMap的数据结构是数组+链表+红黑树。]]></description><category></category></item><item><title><![CDATA[hashmap]]></title><link>https://blog.youkuaiyun.com/gcfffff/article/details/137012737</link><guid>https://blog.youkuaiyun.com/gcfffff/article/details/137012737</guid><author>gcfffff</author><pubDate>Mon, 25 Mar 2024 14:16:40 +0800</pubDate><description><![CDATA[将e.hash小于oldCap的数组元素,也就是低位的元素，通过loTail进行遍历，头节点        放入到loHead中， 同理，将e.hash大于oldCap的数组元素,也就是高位的元素，通        过HiTail进行遍历，头节点放入到HiHead中。由于数组扩容了两倍，但是e.hash没有改变，会导致下标大于oldCap的位置是空着的，所以需要将e.hash小于oldCap的数组元素放入到原来的下标j中，将e.hash大于oldCap的元素放入到新的下标j+oldCap中。]]></description><category></category></item><item><title><![CDATA[2020-08-29]]></title><link>https://blog.youkuaiyun.com/gcfffff/article/details/108292209</link><guid>https://blog.youkuaiyun.com/gcfffff/article/details/108292209</guid><author>gcfffff</author><pubDate>Sat, 29 Aug 2020 11:16:05 +0800</pubDate><description><![CDATA[Java数组转List的三种方式及对比
前言：
本文介绍Java中数组转为List三种情况的优劣对比，以及应用场景的对比，以及程序员常犯的类型转换错误原因解析。
一.最常见方式（未必最佳）
通过 Arrays.asList(strArray) 方式,将数组转换List后，不能对List增删，只能查改，否则抛异常。
关键代码：List list = Arrays.asList(strArray);
private void testArrayCastToListError() {
String[] strAr]]></description><category></category></item><item><title><![CDATA[Java #{}和${}区别]]></title><link>https://blog.youkuaiyun.com/gcfffff/article/details/108157190</link><guid>https://blog.youkuaiyun.com/gcfffff/article/details/108157190</guid><author>gcfffff</author><pubDate>Fri, 21 Aug 2020 20:59:12 +0800</pubDate><description><![CDATA[Java #{}和${}区别
Mybatis中使用#{}可以防止sql注入
#{}: 表示一个占位符号,实现向PreparedStatement占位符中设置值(#{}表示一个占位符?),自动进行Java类型到JDBC类型的转换(因此#{}可以有效防止SQL注入).#{}可以接收简单类型或PO属性值,如果parameterType传输的是单个简单类型值,#{}花括号中可以是value或其它名称.
:表示拼接SQL串,通过:表示拼接SQL串,通过{}可将parameterType内容拼接在SQL中而不进行JDB]]></description><category></category></item></channel></rss>