<?xml version="1.0" encoding="utf-8" ?><rss version="2.0"><channel><title><![CDATA[wsdfym的博客]]></title><description><![CDATA[]]></description><link>https://blog.youkuaiyun.com/wsdfym</link><language>zh-cn</language><generator>https://blog.youkuaiyun.com/</generator><copyright><![CDATA[Copyright &copy; wsdfym]]></copyright><item><title><![CDATA[手把手带你实现 rabbitmq 保证消息不丢失 MQ消息稳定性]]></title><link>https://blog.youkuaiyun.com/wsdfym/article/details/113467318</link><guid>https://blog.youkuaiyun.com/wsdfym/article/details/113467318</guid><author>wsdfym</author><pubDate>Sat, 06 Mar 2021 17:22:06 +0800</pubDate><description><![CDATA[MQ运行图


哪些步骤会发生消息丢失


生产者到MQ之间丢失，网络抖动通信异常。
MQ中的消息还没有完成异步存盘，MQ宕机，再重启消息丢失。
消费者获取到消息之后，没有来得及处理完毕，自己直接宕机了。
属于操作不当，消费者没有将消息投递到对应的Exchange中导致消息丢失

解决方案
MQ宕机之后消息丢失
开启消息持久化
MQ将消息持久化到磁盘中通常情况是，等到有几千条消息的时候，会一次性的刷盘到磁盘上面。消息在MQ内存中还没有刷盘到磁盘就宕机了，消息依旧还是会丢失。需要下面的confirm机制，co]]></description><category></category></item><item><title><![CDATA[FutureTask 源码阅读 使用Callable创建多线程]]></title><link>https://blog.youkuaiyun.com/wsdfym/article/details/114398858</link><guid>https://blog.youkuaiyun.com/wsdfym/article/details/114398858</guid><author>wsdfym</author><pubDate>Fri, 05 Mar 2021 18:08:56 +0800</pubDate><description><![CDATA[接上文线程池源码阅读线程池调用Future&lt;?&gt; submit(Runnable task)；返回一个FutureTsk。
简单使用
public static void main(String[] args) throws ExecutionException, InterruptedException {
        FutureTask&lt;Integer&gt; future = new FutureTask(new MyCallable());
        Thread th]]></description><category></category></item><item><title><![CDATA[了解JVM垃圾回收器]]></title><link>https://blog.youkuaiyun.com/wsdfym/article/details/113896884</link><guid>https://blog.youkuaiyun.com/wsdfym/article/details/113896884</guid><author>wsdfym</author><pubDate>Sun, 21 Feb 2021 14:06:03 +0800</pubDate><description><![CDATA[Serial收集器
这个收集器是一个单线程工作的收集器。

使用一个收集线程去完成垃圾收集工作
它进行垃圾收集时，必须暂停其他所有工作线程，直到它收集结束（“Stop The World”）


Serial Old收集器
ParNew收集器
实质上是Serial收集器的多线程并行版本，除了同时使用多条线程进行垃圾收集之外，其余的行为都与Serial收集器一致

Parallel Scavenge收集器
Parallel Old收集器
CMS收集器
Garbage First收集器
Shenandoah收集]]></description><category></category></item><item><title><![CDATA[JVM垃圾回收算法]]></title><link>https://blog.youkuaiyun.com/wsdfym/article/details/113873293</link><guid>https://blog.youkuaiyun.com/wsdfym/article/details/113873293</guid><author>wsdfym</author><pubDate>Sat, 20 Feb 2021 14:59:29 +0800</pubDate><description><![CDATA[标记-清除算法
算法分为“标记”和“清除”两个阶段：
首先标记出所有需要回收的对象，在标记完成后，统一回收掉所有被标记的对象。
也可以反过来，标记存活的对象，统一回收所有未被标记的对象。标记过程就是对象是否属于垃圾的判定过程。
标记-复制算法
标记-整理算法

...]]></description><category></category></item><item><title><![CDATA[SpringBoot 整合RabbitMQ使用]]></title><link>https://blog.youkuaiyun.com/wsdfym/article/details/113483474</link><guid>https://blog.youkuaiyun.com/wsdfym/article/details/113483474</guid><author>wsdfym</author><pubDate>Sat, 06 Feb 2021 18:02:43 +0800</pubDate><description><![CDATA[添加用户。


none
不能访问 management plugin
management
列出自己可以通过AMQP登入的virtual hosts
查看自己的virtual hosts中的queues, exchanges 和 bindings
查看和关闭自己的channels 和 connections
查看有关自己的virtual hosts的“全局”的统计信息，包含其他用户在这些virtual hosts中的活动。
policymaker
查看、创建和删除自己的virtual hosts所属的po]]></description><category></category></item><item><title><![CDATA[FastJson 泛型解析出错解决]]></title><link>https://blog.youkuaiyun.com/wsdfym/article/details/113612359</link><guid>https://blog.youkuaiyun.com/wsdfym/article/details/113612359</guid><author>wsdfym</author><pubDate>Wed, 03 Feb 2021 16:25:39 +0800</pubDate><description><![CDATA[java.lang.ClassCastException: com.alibaba.fastjson.JSONObject cannot
be cast to X

有问题的写法：
data = (A) JSON.parseObject(str,A.class);

修改之后
data = JSON.parseObject(str, new TypeReference&lt;A&lt;T&gt;&gt;(){});


]]></description><category></category></item><item><title><![CDATA[循环依赖的解决]]></title><link>https://blog.youkuaiyun.com/wsdfym/article/details/111592963</link><guid>https://blog.youkuaiyun.com/wsdfym/article/details/111592963</guid><author>wsdfym</author><pubDate>Wed, 23 Dec 2020 16:41:30 +0800</pubDate><description><![CDATA[是什么
循环依赖，也就是两个或者两个以上的bean互相持有对方，最终形成闭环。
比如A依赖于B，B依赖于C，C又依赖于A。如下图：

代码中的体现
@Component
public class A {
    // A中注入了B
    @Autowired
    private B b;
}

@Component
public class B {
    // B中也注入了A
    @Autowired
    private A a;
}

解决循环依赖的本质
先去缓存Map里找Bean，没有则]]></description><category></category></item><item><title><![CDATA[FactoryBean的使用]]></title><link>https://blog.youkuaiyun.com/wsdfym/article/details/111479449</link><guid>https://blog.youkuaiyun.com/wsdfym/article/details/111479449</guid><author>wsdfym</author><pubDate>Mon, 21 Dec 2020 17:31:54 +0800</pubDate><description><![CDATA[FactoryBean的用法
在某些情况下，实例化bean过程比较复杂，如果还是采用配置的方法，
需要在中提供大量的配置信息，配置方式的灵活性是受限的，
这时采用编码的方式可能会得到一个简单的方案。
Spring为此提供了一个FactoryBean的工厂类接口，用户可以通过实现该接口定制实例化bean的逻辑。
public interface FactoryBean&lt;T&gt; {  
   T getObject() throws Exception;  
   Class&lt;?&gt; get]]></description><category></category></item><item><title><![CDATA[Condition 源码学习]]></title><link>https://blog.youkuaiyun.com/wsdfym/article/details/111185842</link><guid>https://blog.youkuaiyun.com/wsdfym/article/details/111185842</guid><author>wsdfym</author><pubDate>Wed, 16 Dec 2020 16:20:12 +0800</pubDate><description><![CDATA[Condition 解析

]]></description><category></category></item><item><title><![CDATA[ReentrantReadWriteLock 源码学习]]></title><link>https://blog.youkuaiyun.com/wsdfym/article/details/111173252</link><guid>https://blog.youkuaiyun.com/wsdfym/article/details/111173252</guid><author>wsdfym</author><pubDate>Tue, 15 Dec 2020 20:29:11 +0800</pubDate><description><![CDATA[是什么
读写锁在同一时刻可以允许多个读线程访问，但是写线程操作时，所有的读线程和其他写线程均被阻塞。
使用例子
public class LockTest {
    private static ReadWriteLock lock = new ReentrantReadWriteLock();
     /**
     * 读取资源
     */
    public void read() throws InterruptedException {
        lock.readLock().]]></description><category></category></item><item><title><![CDATA[可重入锁 ReentrantLock AQS 源码解析]]></title><link>https://blog.youkuaiyun.com/wsdfym/article/details/110958669</link><guid>https://blog.youkuaiyun.com/wsdfym/article/details/110958669</guid><author>wsdfym</author><pubDate>Fri, 11 Dec 2020 23:22:42 +0800</pubDate><description><![CDATA[使用范例
Lock lock = new ReentrantLock();
lock.lock();
try {
    dosomething();
} finally {
    lock.unlock();
}

在finally块中释放锁，目的是保证在获取到锁之后，最终能够被释放。
接口结构
Lock是个顶级接口，构建了锁的生态环境


void lock();


获取锁。
如果该锁不可用，则出于线程调度目的，当前线程将被禁用，并处于休眠状态，直到获得该锁为止


void lockInterru]]></description><category></category></item><item><title><![CDATA[volatile关键字 可见性 有序性 原子性 内存语义]]></title><link>https://blog.youkuaiyun.com/wsdfym/article/details/102878329</link><guid>https://blog.youkuaiyun.com/wsdfym/article/details/102878329</guid><author>wsdfym</author><pubDate>Wed, 09 Dec 2020 22:51:03 +0800</pubDate><description><![CDATA[理解volatile特性的一个好方法是把对volatile变量的单个读/写，看成是使用同一个锁对这些单个读/写操作做了同步
class VolatileFeaturesExample {
       volatile long vl = 0L;                  // 使用volatile声明64位的long型变量
       public void set(long l) {...]]></description><category></category></item><item><title><![CDATA[JAVA 线程池ThreadPoolExecutor源码阅读与分析]]></title><link>https://blog.youkuaiyun.com/wsdfym/article/details/110825953</link><guid>https://blog.youkuaiyun.com/wsdfym/article/details/110825953</guid><author>wsdfym</author><pubDate>Wed, 09 Dec 2020 00:47:31 +0800</pubDate><description><![CDATA[线程池是什么
提前创建好若干个线程，如果有任务需要处理，这些创建好的线程就会开始处理任务，处理完之后线程并不会被销毁而是被保存起来，而是等待下一个任务。
为什么需要线程池
创建和销毁线程都是消耗系统资源的。
线程模型又分为用户线程，与内核线程。

用户线程ULT
用户程序实现的，不依赖系统核心，应用自己管控线程，不需要进行用户态/内核态的切换。操作系统内核无感知。
内核线程KLT
系统内核管控，内核保存上下文状态和信息，多处理器情况上能并发运行，线程的创建于同步由内核完成，能够调度CPU资源。

一个小测试]]></description><category></category></item><item><title><![CDATA[JAVA retry 使用]]></title><link>https://blog.youkuaiyun.com/wsdfym/article/details/110824838</link><guid>https://blog.youkuaiyun.com/wsdfym/article/details/110824838</guid><author>wsdfym</author><pubDate>Mon, 07 Dec 2020 19:00:06 +0800</pubDate><description><![CDATA[简介
retry不是关键字
他是一个标记有点类似于goto，goto是Java中的保留字，在目前版本的Java中没有使用。
retry后面跟循环，标记这个循环开始的位置。
后续在continue或者break后面加retry。

continue retry
从这个标记的循环继续执行，不是重新开始，而是继续执行。
break retry
跳过这个标记的循环

break retry 例子
public static void main(String[] args) {
    retry:
    for ]]></description><category></category></item><item><title><![CDATA[Java线程池简单使用学习]]></title><link>https://blog.youkuaiyun.com/wsdfym/article/details/110746268</link><guid>https://blog.youkuaiyun.com/wsdfym/article/details/110746268</guid><author>wsdfym</author><pubDate>Mon, 07 Dec 2020 16:34:21 +0800</pubDate><description><![CDATA[常用的五种类型线程池

newFixedThreadPool
newCachedThreadPool
newSingleThreadExecutor
newScheduledThreadPool
newWorkStealingPool

newFixedThreadPool
定长线程池，控制线程最大并发数，超出的任务会在队列中等待。
public static void main(String[] args) {
    ExecutorService pool = Executors.newFixedTh]]></description><category></category></item><item><title><![CDATA[多线程学习之线程的创建与终止]]></title><link>https://blog.youkuaiyun.com/wsdfym/article/details/110408146</link><guid>https://blog.youkuaiyun.com/wsdfym/article/details/110408146</guid><author>wsdfym</author><pubDate>Sun, 06 Dec 2020 16:44:18 +0800</pubDate><description><![CDATA[线程的几种创建模式
通过实现Runnable接口来创建Thread线程：
public class Main {
    public static void main(String[] args) {
        MyThread task = new MyThread();
        Thread thread = new Thread(task);
        thread.start();

    }
    static class MyThread implements Runn]]></description><category></category></item><item><title><![CDATA[延迟队列 DelayQueue 使用与源码解析]]></title><link>https://blog.youkuaiyun.com/wsdfym/article/details/110240657</link><guid>https://blog.youkuaiyun.com/wsdfym/article/details/110240657</guid><author>wsdfym</author><pubDate>Mon, 30 Nov 2020 19:30:37 +0800</pubDate><description><![CDATA[当内存中有一堆的客户信息，需要实时移除VIP到期的客户的特权时有以下做法。

做法1：
定时一段时间检查一遍所有的元素，如果客户的VIP到期日期小于当前，则取消客户的VIP特权。
做法2：
利用优先队列小顶堆的结构，将最快要过期的客户信息放置在堆顶，一个消费线程去poll堆顶元素并且处理，这样就不用去遍历全部的元素了。当日期不到时便让线程等待多长时间，当时间到时唤醒线程处理。

以上做法2有现成的队列可以使用，就是接下来要说的延迟队列。
DelayQueue结构
是不是跟优先队列很像。DelayQueue其]]></description><category></category></item><item><title><![CDATA[PriorityQueue  PriorityBlockingQueue 优先级队列与优先级阻塞队列 源码解析]]></title><link>https://blog.youkuaiyun.com/wsdfym/article/details/110145082</link><guid>https://blog.youkuaiyun.com/wsdfym/article/details/110145082</guid><author>wsdfym</author><pubDate>Thu, 26 Nov 2020 17:32:25 +0800</pubDate><description><![CDATA[试想一下，如果要在一堆数据中找出最大的或者最小的是不要进行一次遍历，时间复杂度为O（N）
还能不能优化，比如O（1）的时间复杂度就能获取到。这就是这篇博客需要说的PriorityQueue优先级队列。
先看结构
完全二叉树：一棵有n个结点的二叉树，对树中的结点按从上至下、从左到右的顺序进行编号，节点得插入永远在下一个位置。
下面得紫色的那排小字就是节点的序号。那么第N个元素的左孩子queue [2 * n + 1]右孩子就是queue [2 *（n + 1）]。看到源码就会发现PriorityQueue存储]]></description><category></category></item><item><title><![CDATA[BlockingQueue 的使用与源码阅读]]></title><link>https://blog.youkuaiyun.com/wsdfym/article/details/110055934</link><guid>https://blog.youkuaiyun.com/wsdfym/article/details/110055934</guid><author>wsdfym</author><pubDate>Wed, 25 Nov 2020 19:04:13 +0800</pubDate><description><![CDATA[结构
其中数组是循环使用的，真实中不存在从3到1的指针，使用的是putIndex，takeIndex两个下标索引。当此时存放的元素putIndex等于数组的长度-1时，putIndex下次就会变成0，又从头开始存放元素。takeIndex原理一样。

基于数组实现的，并且内部持有一把ReentrantLock（读写一把）。
ArrayBlockingQueue的使用

简单说一下情况，后面从方法中分析。生产线程将元素放入队列中时需要先获取锁，获取到锁后向队列存放元素。消费线程获取队列中元素时也需要先获取锁，]]></description><category></category></item><item><title><![CDATA[数组 List 去除重复数据 多种实现及性能分析]]></title><link>https://blog.youkuaiyun.com/wsdfym/article/details/109806371</link><guid>https://blog.youkuaiyun.com/wsdfym/article/details/109806371</guid><author>wsdfym</author><pubDate>Sun, 22 Nov 2020 15:01:28 +0800</pubDate><description><![CDATA[有序的情况下去重
单指针法：前者与后者比
01、使用两个for循环实现List去重(有序)双层针法：
02、使用List集合contains方法循环遍历(有序)双层针法：contains方法调用indexof方法，内部实现还是循环遍历
03、使用HashSet实现List去重(无序)
04、使用TreeSet实现List去重(有序)
05、使用java8新特性stream实现List去重(有序)
桶排序法：

...]]></description><category></category></item></channel></rss>