<?xml version="1.0" encoding="utf-8" ?><rss version="2.0"><channel><title><![CDATA[GJ_863的博客]]></title><description><![CDATA[]]></description><link>https://blog.youkuaiyun.com/GJ_863</link><language>zh-cn</language><generator>https://blog.youkuaiyun.com/</generator><copyright><![CDATA[Copyright &copy; GJ_863]]></copyright><item><title><![CDATA[分布式定时任务Quartz框架介绍]]></title><link>https://blog.youkuaiyun.com/GJ_863/article/details/144172681</link><guid>https://blog.youkuaiyun.com/GJ_863/article/details/144172681</guid><author>GJ_863</author><pubDate>Sun, 01 Dec 2024 18:08:15 +0800</pubDate><description><![CDATA[之前在项目中用定时任务都是直接用的Spring的@Scheduled注解，因为遇到的业务都比较简单，比如定时更新榜单，支付功能中的定时查单，最近在写一个课堂助手的项目，要实现定时任务的业务对任务有增删改查的需求，@Scheduled已经无法满足了，so，我选择了QuartzQuartz是OpenSymphony开源的一个项目，是一个由Java编写的开源作业调度框架。]]></description><category></category></item><item><title><![CDATA[Java实现异步编程]]></title><link>https://blog.youkuaiyun.com/GJ_863/article/details/144165190</link><guid>https://blog.youkuaiyun.com/GJ_863/article/details/144165190</guid><author>GJ_863</author><pubDate>Sun, 01 Dec 2024 09:39:55 +0800</pubDate><description><![CDATA[Spring中提供了多种线程池SyncTaskExecutor：这个类没有实现异步调用，只是一个同步操作。只适用于不需要多线程的地方。ConcurrentTaskExecutor：Executor的适配类，不推荐使用。ThreadPoolTaskScheduler：支持定时任务ThreadPoolTaskExecutor：本质是对java.util.concurrent.ThreadPoolExecutor的包装。]]></description><category></category></item><item><title><![CDATA[SpringBoot接入星火认知大模型]]></title><link>https://blog.youkuaiyun.com/GJ_863/article/details/143436677</link><guid>https://blog.youkuaiyun.com/GJ_863/article/details/143436677</guid><author>GJ_863</author><pubDate>Fri, 01 Nov 2024 17:24:26 +0800</pubDate><description><![CDATA[客户端，服务端，星火大模型均通过Websocket的方式建立连接，用户询问问题时向SpringBoot服务端发送消息，服务端接收到后，创建与星火大模型的连接，并访问大模型，获取到请求结果后发送给客户端。申请成功后可以获得对应的secret，key还有之前创建的应用的appId，这些就是我们要用到的信息。考虑到敏感信息等安全性问题，这里和大模型的交互都放到后端去做。请求参数的构建和响应参数解析参照官方文档。上根据官方的提示申请tokens。这样就简单实现了一个ai问答功能。其中用来接收响应参数相关实体类。]]></description><category></category></item><item><title><![CDATA[接口限流经典算法]]></title><link>https://blog.youkuaiyun.com/GJ_863/article/details/141496378</link><guid>https://blog.youkuaiyun.com/GJ_863/article/details/141496378</guid><author>GJ_863</author><pubDate>Sat, 24 Aug 2024 11:23:29 +0800</pubDate><description><![CDATA[为了保证系统的安全性和稳定性，防止恶意流量和突发大量流量短时间内大量请求接口，造成服务器崩溃，接口的限流是有必要的。控制水流稳定流出，进水就是向接口发起的请求，一定有时快有时慢，但是漏水的速度是一定的，只要桶装满了就拒绝请求。漏桶里面的任务是一点点执行的，令牌桶有可能一下子把令牌全用光一起执行，这样就可以很快的处理大流量的请求。如果切分越小，产生的块就多，窗口滚动越平滑，限流统计越准确，但是对服务器压力越大。把令牌以稳定的速度放入桶中，如果桶被放满了，多余的令牌就无法放入。以下是四种经典的限流算法。]]></description><category></category></item><item><title><![CDATA[nginx反向代理了解]]></title><link>https://blog.youkuaiyun.com/GJ_863/article/details/139424659</link><guid>https://blog.youkuaiyun.com/GJ_863/article/details/139424659</guid><author>GJ_863</author><pubDate>Mon, 03 Jun 2024 21:09:09 +0800</pubDate><description><![CDATA[cgi：通用网关（接口），主要解决的问题是从客户端发送请求和数据，服务端获取到请求和数据后可以调用cgi程序处理及相应结果给客户端的一种标准规范。正向代理代理的是客户端（如翻墙），反向代理代理的是服务端，用户请求代理服务器，代理服务器再将请求分发到服务端。客户端将请求发送给代理，代理再向服务端请求，并接受服务端响应，将响应返回给客户端，比如翻墙。客户端将请求发送给代理，代理将请求发送给不同的服务端，把服务端隐藏起来，降低服务端压力。设置被代理服务器地址，可以是主机名称，ip地址+端口形式。]]></description><category></category></item><item><title><![CDATA[ElasticSearch学习]]></title><link>https://blog.youkuaiyun.com/GJ_863/article/details/139046455</link><guid>https://blog.youkuaiyun.com/GJ_863/article/details/139046455</guid><author>GJ_863</author><pubDate>Sun, 19 May 2024 18:32:03 +0800</pubDate><description><![CDATA[拼音分词器会将词一个字一个字的转成拼音，而且没有中文，所以我们还要修改拼音分词器的配置es中的分词器组成包含三部分character filters：在tokenizer之前对文本进行处理，例如删除字符，替换字符tokenizer：将文本按照一定规则切割成词条tokenizer filter：将tokenizer输出的词条做进一步处理，例如大小写转化，同义词处理，拼音处理等可以在创建分词库时，通过setting来配置自定义的analyzer（分词器）PUT /test。]]></description><category></category></item><item><title><![CDATA[Rabbitmq学习]]></title><link>https://blog.youkuaiyun.com/GJ_863/article/details/138280763</link><guid>https://blog.youkuaiyun.com/GJ_863/article/details/138280763</guid><author>GJ_863</author><pubDate>Sun, 28 Apr 2024 15:47:22 +0800</pubDate><description><![CDATA[如果我们向消息队列中发送Java对象，spring对消息对象的处理是由MessageConverter来处理的，而默认实现是SimpleMessageConverter，会基于jdk的ObjectOutputStream完成序列化。当一个服务完成后需要调用其他服务，这个服务不需要主动调用其他服务，可以向事件代理者（Broker）发布事件，事件代理者就会通知相应服务执行相关业务，这个服务也不需要等待其他服务执行完直接返回结果给用户即可。工作消息队列：一个队列绑定多个消费者，提高消息处理速度，避免消息堆积。]]></description><category></category></item><item><title><![CDATA[Docker的使用]]></title><link>https://blog.youkuaiyun.com/GJ_863/article/details/137999418</link><guid>https://blog.youkuaiyun.com/GJ_863/article/details/137999418</guid><author>GJ_863</author><pubDate>Sat, 20 Apr 2024 14:45:49 +0800</pubDate><description><![CDATA[镜像是分层结构，每一层称为一个LayerBaseImage层：包含基本的系统函数库，环境变量，文件系统Entrypoint：入口，是镜像中应用启动的命令其他：在BaseImage基础上添加依赖，安装程序，完成整个应用的安装和配置。]]></description><category></category></item><item><title><![CDATA[Redis分片集群]]></title><link>https://blog.youkuaiyun.com/GJ_863/article/details/137723896</link><guid>https://blog.youkuaiyun.com/GJ_863/article/details/137723896</guid><author>GJ_863</author><pubDate>Sat, 13 Apr 2024 20:03:50 +0800</pubDate><description><![CDATA[我们通过故意将一个master端口的Redis宕机，可以发现之后redis自动选取了他的从节点作为新的master，原来的宕机的那个在重新启动后，变成了slave，整个过程不需要哨兵，自动完成。实际业务中，可能由于某台master老旧，就为他添加了新的slave，想要将这个新的slave变成master，实现手动故障转移。而且，如果key时和节点绑定，节点宕机后，数据就丢失了，而和插槽绑定，节点宕机后将他上面的插槽转移即可。如果是新添加一个master，上面一开始是没有插槽的，我们可以使用。]]></description><category></category></item><item><title><![CDATA[消息队列Redis实现]]></title><link>https://blog.youkuaiyun.com/GJ_863/article/details/137465250</link><guid>https://blog.youkuaiyun.com/GJ_863/article/details/137465250</guid><author>GJ_863</author><pubDate>Sun, 07 Apr 2024 15:25:07 +0800</pubDate><description><![CDATA[但是由于$代表读最新的消息，如果我们处理一条消息的过程中，又有超过一条消息到达消息队列，则下次只能获取最新的那条消息，出现漏读消息的问题。消费者可以订阅一个或多个channel，生产者向对应channel发送消息后，所有订阅者都能收到相关消息，就实现了。一般不需要手动创建消费者，当我们指定一个组去监听消息时，如果他发现组中没有消费者，会自动帮我们创建。缺点：不支持数据持久化，无法避免数据丢失，消息堆积有上限，超出时数据丢失。pubsub：基本的点对点消息模型。消息可以回溯，可以被多个消费者读取。]]></description><category></category></item><item><title><![CDATA[基于Redis实现分布式锁]]></title><link>https://blog.youkuaiyun.com/GJ_863/article/details/137193697</link><guid>https://blog.youkuaiyun.com/GJ_863/article/details/137193697</guid><author>GJ_863</author><pubDate>Sun, 31 Mar 2024 10:13:46 +0800</pubDate><description><![CDATA[线程1拿到锁后执行业务完毕，对比完锁中的线程标识和自己的线程标识，正准备释放锁，但此时发生了阻塞（可能是jvm的full gc等问题），锁超时释放，线程2拿到了锁，此时线程1的阻塞结束，释放了锁，线程3又能拿到锁，这样线程2和线程3都在执行业务，产生并发问题。Redisson的可重试不是无休止的等待和重试，而是利用Redis的订阅发布和信号量，在锁彻底被释放时，发布一条消息，正在等待重试的线程一旦接收到这样的消息，就会先判断时间是否超出最大等待时间，没有就进行抢锁，期间也会不断校验是否超出最大等待时间。]]></description><category></category></item><item><title><![CDATA[ConcurrentHashMap源码分析]]></title><link>https://blog.youkuaiyun.com/GJ_863/article/details/136988775</link><guid>https://blog.youkuaiyun.com/GJ_863/article/details/136988775</guid><author>GJ_863</author><pubDate>Sun, 24 Mar 2024 15:58:24 +0800</pubDate><description><![CDATA[如果需要添加的链表已经存在哈希表table中，则通过tabAt方法，基于volatile机制，获取当前最新的链表头结点f，由于f指向的是ConcurrentHashMap的哈希表table的某条。如果当前需要put的key对应的链表在哈希表table中还不存在，即还没添加过该key的hash值对应的链表，则调用casTabAt方法，基于CAS机制来实现添加该链表头结点到哈希表。HashMap一样遍历该链表，如果该key对应的链表节点已经存在，则更新，否则在链表的末尾新增该key对应的链表节点。]]></description><category></category></item><item><title><![CDATA[AQS源码分析]]></title><link>https://blog.youkuaiyun.com/GJ_863/article/details/136781920</link><guid>https://blog.youkuaiyun.com/GJ_863/article/details/136781920</guid><author>GJ_863</author><pubDate>Sun, 17 Mar 2024 14:41:34 +0800</pubDate><description><![CDATA[自定义同步器的共享方式要么是独占（ReentrantLock），要么是共享（CountDownLatch/Semaphore），但是aqs也支持同时实现独占和共享的两种方式（ReentrantReadWriteLock）每个节点由线程封装，当线程抢夺锁失败后会封装成节点加入aqs队列中，通过cas，自旋以及LockSupport.park()的方式维护state变量状态，获取锁的线程释放锁后，随机从队列中唤醒一个阻塞的节点。Lock接口的实现类基本都是通过聚合了一个队列同步器的子类完成线程访问控制的。]]></description><category></category></item><item><title><![CDATA[AtomicInteger原理]]></title><link>https://blog.youkuaiyun.com/GJ_863/article/details/136605225</link><guid>https://blog.youkuaiyun.com/GJ_863/article/details/136605225</guid><author>GJ_863</author><pubDate>Sun, 10 Mar 2024 17:26:15 +0800</pubDate><description><![CDATA[AtomicInteger的本质：自旋锁 + CAS算法：当一个线程在获取锁时，如果锁已经被其他线程获取，当前线程就会不断循环检查锁是否被释放，直到获取到锁CAS的全成是： Compare And Swap(比较再交换);是现代CPU广泛支持的一种对内存中的共享数据进行操作的一种特殊指令。CAS可以将read-modify-write转换为原子操作，这个原子操作直接由处理器保证。CAS有3个操作数，内存值V，旧的预期值A，要修改的新值B。]]></description><category></category></item><item><title><![CDATA[ThreadLocal介绍]]></title><link>https://blog.youkuaiyun.com/GJ_863/article/details/136423600</link><guid>https://blog.youkuaiyun.com/GJ_863/article/details/136423600</guid><author>GJ_863</author><pubDate>Sat, 02 Mar 2024 22:09:10 +0800</pubDate><description><![CDATA[ThreadLocal中作为map中的key使用，而且ThreadLocalMap中的key是弱引用，弱引用对象在gc时会被回收，而ThreadLocalMap和Thread的生命周期一样长，就会存在key为null的情况，value访问不到，从而引发内存泄漏。ThreadLocal提供了线程局部变量，每个线程都可以通过set和get方法来对这个变量进行操作，但不会和其他线程的局部变量冲突，实现了线程的数据隔离。内存溢出：要求分配的内存超过了系统能给的。]]></description><category></category></item><item><title><![CDATA[JVM类加载机制]]></title><link>https://blog.youkuaiyun.com/GJ_863/article/details/135998928</link><guid>https://blog.youkuaiyun.com/GJ_863/article/details/135998928</guid><author>GJ_863</author><pubDate>Fri, 02 Feb 2024 18:13:47 +0800</pubDate><description><![CDATA[同时，在堆中生成一份与方法区中数据类似的java.lang.Class对象（用来在Java代码中去获取类的信息以及存储静态字段的数据，JDK8之后·这个静态字段数据就存放在堆区）类加载器加载完类后，Java虚拟机会将字节码中的信息保存到方法区，在方法区中生成一个对象InstanceKlass，保存所有类的信息，里边包含实现特定功能，如多态的信息。扩展类加载器和应用类加载器的源码位于rt.jar包中的sun.misc.Launcher.java，是按照jar包的位置来加载字节码文件。这种方式性能比较高。]]></description><category></category></item><item><title><![CDATA[基础算法--搜索与图论（2）]]></title><link>https://blog.youkuaiyun.com/GJ_863/article/details/135886406</link><guid>https://blog.youkuaiyun.com/GJ_863/article/details/135886406</guid><author>GJ_863</author><pubDate>Sat, 27 Jan 2024 18:21:10 +0800</pubDate><description><![CDATA[实际上是对Bellman-ford算法的优化，主要思路是记录哪些点被更新了，再将和这些点有关系的点更新。所有边权重都是正数：朴素Dijkstra算法 n^2，堆优化版Dijkstra算法 mlogn。存在负权边：Bellman-Ford算法  nm   ，SPFA 算法 一般是m，最坏nm。图中不能存在负权回路，否则在回路中一直转圈，最短路就变成负无穷即不存在最短路。**单源最短路：**一个点到其他点的最短距离。**多源汇最短路：**起点和终点都是不确定的。到集合的距离：指到集合中的最近的点的距离。]]></description><category></category></item><item><title><![CDATA[基础算法--搜索与图论（1）]]></title><link>https://blog.youkuaiyun.com/GJ_863/article/details/135314174</link><guid>https://blog.youkuaiyun.com/GJ_863/article/details/135314174</guid><author>GJ_863</author><pubDate>Sun, 31 Dec 2023 11:12:39 +0800</pubDate><description><![CDATA[对于一个序列，对应图上每条边都是起点在终点前面易知，如果存在环的话，就一定不存在拓扑序列所以，有向无环图又被称为拓扑图入度为0的点可以作为起点，所以，拓扑排序步骤如下：把所有入度为0的点入队。]]></description><category></category></item><item><title><![CDATA[Manacher算法（马拉车）]]></title><link>https://blog.youkuaiyun.com/GJ_863/article/details/135078445</link><guid>https://blog.youkuaiyun.com/GJ_863/article/details/135078445</guid><author>GJ_863</author><pubDate>Tue, 19 Dec 2023 10:21:59 +0800</pubDate><description><![CDATA[作用：在On的时间复杂度下，求出字符串每个回文中心的最长回文半径回文半径：以回文中心为起点，到回文串两端的距离如：#  a  #  b  #  a  #以b为回文中心，最长回文半径就是 4如果回文字符串长度为偶数，那么回文中心就无法正好落在某个字符上，所以可以在每个字符之间添加一个“#”做前置处理（包括字符串首尾）]]></description><category></category></item><item><title><![CDATA[算法--数据结构基础]]></title><link>https://blog.youkuaiyun.com/GJ_863/article/details/135029363</link><guid>https://blog.youkuaiyun.com/GJ_863/article/details/135029363</guid><author>GJ_863</author><pubDate>Sat, 16 Dec 2023 10:16:14 +0800</pubDate><description><![CDATA[在读数据的同时维护一个栈，如果栈不为空，就比较栈顶元素和当前要加入的元素的大小，如果大于或等于当前元素，就将栈顶元素弹出，直到新的栈顶元素比当前元素小，就停止循环弹出栈顶元素，如果此时栈不为空，那么栈顶元素即答案，栈为空答案为-1，最后将当前元素入栈。定义数组q[ ] ，hh为头下标初始为0，tt为尾，初始为-1，尾部添加元素，添加时，q[++tt] = x，头部删除，删除hh++即可。size - -;查看队列是否为空，只用看hh<=tt，如果是，不为空，不是就为空，查看队头元素只用看q[hh]]]></description><category></category></item></channel></rss>