
Java
文章平均质量分 66
皮皮攻城狮
写博客的目的是记录生活的点点滴滴,与大家共享知识,记录解决每一个小小的问题。
方便我自己,也方便大家!这是初心!
展开
-
你有哪些手段来排查 OOM 的问题?
(1)增 加 两 个 参 数 -XX:+HeapDumpOnOutOfMemoryError - XX:HeapDumpPath=/tmp/heapdump.hprof,当 OOM 发生时自动 dump 堆内存信息到指定目录。(3)使用 MAT 工具载入到 dump 文件,分析大对象的占用情况,比如 HashMap 做缓存未清理,时间长了就会内存溢出,可以把改为弱引用。(2)同时 jstat 查看监控 JVM 的内存和 GC 情况,先观察问题大概出在什么区域。原创 2024-01-13 11:18:47 · 399 阅读 · 0 评论 -
java线程池大小如何设置
(1)CPU 密集型任务(N+1): 这种任务消耗的主要是 CPU 资源,可以将线程数设置为 N(CPU 核心数)+1,比 CPU 核心数多出来的一个线程是为了防止线程偶发的缺页中断, 或者其它原因导致的任务暂停而带来的影响。一旦任务暂停,CPU 就会处于空闲状态,而在这种情况下多出来的一个线程就可以充分利用 CPU 的空闲时间。原创 2024-01-13 11:17:53 · 468 阅读 · 0 评论 -
ThreadLocal 是什么?它的实现原理是什么?
但是加锁会带来性能的下降,所以 ThreadLocal 用了一种空间换时间的设计思想, 也就是说在每个线程里面,都有一个容器来存储共享变量的副本,然后每个线程 只对自己的变量副本来做更新操作,这样既解决了线程安全问题,又避免了多线程竞争加锁的开销。在多线程访问共享变量的场景中,一般的解决办法是对共享变量加锁,从而保证在同一时刻只有一个线程能够对共享变量进行更新,并且基于 Happens-Before 规则里面的监视器锁规则,又保证了数据修改后对其他线程的可见性。原创 2024-01-01 17:52:55 · 476 阅读 · 0 评论 -
wait 和 notify 这个为什么要在synchronized 代码块中
而 Synchronized 同步关键字就可以实现这样一个互斥条件,也就是在通过共享变量来实现多个线程通信的场景里面,参与通信的线程必须要竞争到这个共享变量的锁资源,才有资格对共享变量做修改,修改完成后就释放锁,那么其他的线程就可以再次来竞争同一个共享变量的锁来获取修改后的数据,从而完成线程之前的通信。在多线程里面,要实现多个线程之间的通信,除了管道流以外,只能通过共享变量的方法来实现,也就是线程 t1 修改共享变量 s,线程 t2 获取修改后的共享变量 s,从而完成数据通信。原创 2024-01-01 17:36:51 · 584 阅读 · 1 评论 -
网络四元组
今天我们来聊聊 网络四元组。原创 2024-01-01 17:28:33 · 659 阅读 · 0 评论 -
Dubbo 的服务请求失败怎么处理?
而对于 Dubbo 服务请求失败的场景,默认提供了重试的容错机制,也就是说, 如果基于 Dubbo 进行服务间通信出现异常,服务消费者会对服务提供者集群中其他的节点发起重试,确保这次请求成功,默认的额外重试次数是 2 次。并行调用多个服务策略,就是把这个消息广播给服务提供者集群,只要有任何一个节点返回,就表示请求执行成功。要注意的是,默认基于重试策略的容错机制中,需要注意幂等性的处理,否则在事务型的操作中,容易出现多次数据变更的问题。失败安全策略,如果出现服务通信异常,直接把这个异常吞掉不做任何处理。原创 2024-01-01 17:23:21 · 591 阅读 · 0 评论 -
CPU 飙高系统反应慢怎么排查
CPU 利用率过高的线程一直是同一个,说明程序中存在线程长期占用 CPU 没有释放的情况,这种情况直接通过 jstack 获得线程的 Dump 日志,定位到线程日志后就可以找到问题的代码。一、CPU 上下文切换过多,对于 CPU 来说,同一时刻下每个 CPU 核心只能运行一个线程,如果有多个线程要执行,CPU 只能通过上下文切换的方式来执行不同的线程。CPU 利用率过高的线程 id 不断变化,说明线程创建过多,需要挑选几个线程 id, 通过 jstack 去线程 dump 日志中排查。原创 2023-12-31 10:07:33 · 434 阅读 · 0 评论 -
CompletableFuture是什么?以及CompletableFuture的作用
今天我们来聊聊 CompletableFuture。原创 2023-12-30 11:40:48 · 558 阅读 · 0 评论 -
什么是 SPI,它有什么用?
SPI 全称是 Service Provider Interface ,它是 JDK 内置的一种动态扩展点的实现。简单来说,就是我们可以定义一个标准的接口,然后第三方的库里面可以实现这个接口。那么,程序在运行的时候,会根据配置信息动态加载第三方实现的类,从而完成功能的动态扩展机制。在 Java 里面, SPI 机制有一个非常典型的实现案例, 就是数据库驱动 java.jdbc.DriverJDK 里面定义了数据库驱动类 Driver,它是一个接口,JDK 并没有提供实现。原创 2023-12-30 11:33:28 · 564 阅读 · 0 评论 -
为什么引入偏向锁、轻量级锁,介绍下升级流程 Synchronized 引入了锁升级的机制之后,如果有线程去竞争锁:
Synchronized 在 jdk1.6 版本之前,是通过重量级锁的方式来实现线程之间锁的竞争。之所以称它为重量级锁,是因为它的底层底层依赖操作系统的 Mutex Lock 来实现互斥功能。Mutex 是系统方法,由于权限隔离的关系,应用程序调用系统方法时需要切换到内核态来执行。这里涉及到用户态向内核态的切换,这个切换会带来性能的损耗。在 jdk1.6 版本中,synchronized 增加了锁升级的机制,来平衡数据安全性和性能。原创 2023-12-29 21:51:10 · 760 阅读 · 0 评论 -
Seata 中封装了四种分布式事务模式,分别是: AT 模式, TCC 模式, Saga 模式, XA 模式,
在微服务架构下,由于数据库和应用服务的拆分,导致原本一个事务单元中的多个 DML 操作,变成了跨进程或者跨数据库的多个事务单元的多个 DML 操作,而传统的数据库事务无法解决这类的问题,所以就引出了分布式事务的概念。分布式事务本质上要解决的就是跨网络节点的多个事务的数据一致性问题,业内常见的解决方法有两种强一致性,就是所有的事务参与者要么全部成功,要么全部失败,全局事务协调 者需要知道每个事务参与者的执行状态,再根据状态来决定数据的提交或者回滚!原创 2023-12-28 22:57:37 · 644 阅读 · 0 评论 -
什么是受检异常和非受检异常 一、首先是异常的本质 二、然后是对受检异常和非受检异常的定义 三、最后我还可以说下他们优点和缺点) 受检异常优点有两个:
可以从三个方面回答这个问题一、首先是异常的本质)前面说过受检异常和非受检异常均派生自 Exception 这个类。\1. 受检异常的定义是程序在编译阶段必须要主动捕获的异常,遇到该异常有两种处理方法通过 try/catch 捕获该异常或者通过 throw 把异常抛出去\2. 非受检异常的定义是程序不需要主动捕获该异常,一般发生在程序运行期间, 比如 NullPointException第一,它可以响应一个明确的错误机制,这些错误在写代码的时候可以随时捕获并且能很好的提高代码的健壮性。原创 2023-12-28 22:49:36 · 785 阅读 · 0 评论 -
Zookeeper 和 Redis 哪种更好? 为什么使用分布式锁? 1. 利用 Redis 提供的 第二种,基于 ZK 实现分布式锁的落地方案 对于 redis 的分布式锁而言,它有以下缺点:
如果要在两者之间做选择,就我个人而言的话,比较推崇 ZK 实现的锁,因为对于分布式锁而言,它应该符合 CP 模型,但是 Redis 是 AP 模型,所以在这个点上,Zookeeper 会更加合适。4、如果当前线程创建的节点不是所有节点序号最小的节点,则对节点序号的前一个节点添加一个事件监听,当前一个被监听的节点释放锁之后,触发回调通知, 从而再次去尝试抢占锁。2、线程创建节点后,获取/lock 节点下的所有子节点,判断当前线程创建的节点是否是所有的节点的序号最小的。锁的模型健壮、简单易用、适合做分布式锁。原创 2023-12-28 22:43:48 · 1107 阅读 · 0 评论 -
spripng 三级缓存,三级缓存的作用是什么? Spring 中哪些情况下,不能解决循环依赖问题有哪些
三级缓存是用来存储代理 Bean,当调用 getBean()方法时,发现目标 Bean 需要通过代理工厂来创建,此时会将创建好的实例保存到三级缓存,最终也会将赋值好的 Bean 同步到一级缓存中。3.单例的代理 Bean 通过 Setter 注入的情况,不能解决循环依赖问题。4.设置了@DependsOn 的 Bean 的情况,不能解决循环依赖问题。1.多例 Bean 通过 setter 注入的情况,不能解决循环依赖问题。2.构造器注入的 Bean 的情况,不能解决循环依赖问题。原创 2023-12-27 23:16:17 · 682 阅读 · 0 评论 -
Spring 是如何解决循环依赖问题的方案
而 Spring 中设计了三级缓存来解决循环依赖问题,当我们去调用 getBean()方法的时候,Spring 会先从一级缓存中去找到目标 Bean,如果发现一级缓存中没有便会去二级缓存中去找,而如果一、二级缓存中都没有找到,意味着该目标 Bean 还没有实例化。如果不存在循环依赖便会将目标 Bean 存入到二级缓存,否则, 便会标记该 Bean 存在循环依赖,然后将等待下一次轮询赋值,也就是解析。循环的依赖将会导致注入死循环。第二种三者间依赖:A 依赖 B,B 依赖 C,C 又依赖 A,形成了循环依赖。原创 2023-12-27 23:12:06 · 564 阅读 · 0 评论 -
Dubbo 的工作原理是什么样的? 最后在说说 Dubbo 与 Spring Cloud 的区别吧!
Dubbo 是 SOA 时代的产物,它的关注点主要在于服务的调用,流量分发、流量监控和熔断。而 Spring Cloud 诞生于微服务架构时代,考虑的是微服务治理的方方面面,另外由于依托了 Spirng、Spirng Boot 的优势之上,两个框架在开始目标就不一致,Dubbo 定位服务治理、Spirng Cloud 是一个生态。两者最大的区别是 Dubbo 底层是使用 Netty 这样的 NIO 框架,是基于 TCP 协议传输的,配合以 Hession 序列化完成 RPC 通信。原创 2023-12-24 09:01:37 · 422 阅读 · 0 评论 -
既然说到 Dubbo 的功能,请详细说说 Dubbo 负载均衡的几种策略 Dubbo 有五种负载策略:
每收到一个请求,活跃数加 1,完成请求后则将活跃数减 1。在服务运行一段时间后,性能好的服务提供者处理请求的速度更快, 因此活跃数下降的也越快,此时这样的服务提供者能够优先获取到新的服务请求。现在把这些权重值平铺在一维坐标值上,[0, 5) 区间属于服务器 A,[5, 8) 区间属于服务器 B,[8, 10) 区间属于服。比如服务器 A、B、C 权重比为 5:2:1,那么在 8 次请求中, 服务器 A 将收到其中的 5 次请求,服务器 B 会收到其中的 2 次请求,服务器 C 则收到其中的 1 次请求。原创 2023-12-24 08:58:41 · 481 阅读 · 0 评论 -
什么是 Dubbo?它有哪些核心功能?
Dubbo 是一款高性能、轻量级的开源 RPC 框架。由 10 层模式构成,整个分层依赖由上至下。通过这张图我们也可以将 Dubbo 理解为三层模式:第一层的 Business 业务逻辑层由我们自己来提供接口和实现还有一些配置信息。第二层的 RPC 调用的核心层负责封装和实现整个 RPC 的调用过程、负载均衡、集群容错、代理等核心功能。Remoting 则是对网络传输协议和数据转换的封装。l 面向接口代理的高性能 RPC 调用。l 智能容错和负载均衡。l 服务自动注册和发现。原创 2023-12-24 08:56:32 · 590 阅读 · 0 评论 -
1、TCP 和 UDP 区别? 2、TCP/IP 协议涉及哪几层架构? 3、描述下 TCP 连接 4 次挥手的过程?为什么要 4 次挥手?
因为 TCP 是全双工,每个方向都必须进行单独关闭。关闭连接时,当 Server 端收到 FIN 报文时,很可能并不会立即关闭 SOCKET,所以只能先回复一个 ACK 报文,告诉 Client 端,”你发的 FIN 报文我收到了”。只有等到 Server 端所有的报文都发送完了,我才能发送 FIN 报文,因此不能一起发送。(4)TCP 保证数据正确性,UDP 可能丢包。(2)TCP 要求系统资源较多,UDP 较少。(1)TCP 基于连接,UDP 基于无连接。(5)TCP 保证数据顺序,UDP 不保证。原创 2023-12-23 23:10:23 · 1280 阅读 · 0 评论 -
LRU 是什么?如何实现? 什么是堆内存?参数如何设置?
堆内存是指由程序代码自由分配的内存,与栈内存作区分。在 Java 中,堆内存主要用于分配对象的存储空间,只要拿到对象引用,所有线程都可以访问堆内存。(1)-Xmx, 指定最大堆内存。如 -Xmx4g. 这只是限制了 Heap 部分的最大值为 4g。这个内存不包括栈内存,也不包括堆外使用的内存。(2)-Xms, 指定堆内存空间的初始大小。如 -Xms4g。而且指定的内存大小,并不是操作系统实际分配的初始值,而是 GC 先规划好,用到才分配。原创 2023-12-23 22:54:35 · 1067 阅读 · 0 评论 -
可重复读解决了哪些问题? 对 SQL 慢查询会考虑哪些优化 ?
保证多次读取同一个数据时,其值都和事务开始时候的内容是一致,禁止读取到别的事务未提交的数据,会造成幻读。(2)而事务更新数据的时候,只能用当前读。(2)分析 SQL 执行计划(explain extended),思考可能的优化点,是否命中索引等。(4)可重复读解决的是重复读的问题,可重复读在快照读的情况下是不会有幻读,但当前读的时候会有幻读。(5)按照可能的优化点执行表结构变更、增加索引、SQL 改写等操作。(1)分析语句,是否加载了不必要的字段/数据。(3)查看 SQL 涉及的表结构和索引信息。原创 2023-12-23 22:52:48 · 908 阅读 · 0 评论 -
java 线程的创建和启动
每个线程的作用是完成一定的任务,实际上就是执行一段程序流。call()**方法将作为线程执行体,并且有返回值。方法的方法体就代表了线程要完成的任务。()方法的方法体同样是该线程的线程执行体。对象的**call()**方法的返回值。()方法来获得子线程执行结束后的返回值。接口的实现类,并实现**call()类代表线程,所有的线程对象都必须是。子类的实例,即创建了线程对象。接口的实现类,并重写该接口的。对象才是真正的线程对象。类的子类,并重写该类的。()方法来启动该线程。()方法来启动该线程。原创 2023-12-22 08:17:14 · 1323 阅读 · 0 评论 -
1. 线程概述、线程和进程、 并发和并行、多线程的优势 、程序运行原理 、主线程、 线程的 6 种状态
进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位。线程也被称为轻量级进程,线程是进程的组成部分,一个进程可以拥有多个线程,一个线程必须有一个父进程。线程可以拥有自己的堆栈、自己的程序计数器和自己的局部变量,但不拥有系统资源,它与父进程的其它线程共享该进程所拥有的全部资源。一个线程可以创建和撤销另一个线程,同一个进程中的多个线程之间可以并发执行。原创 2023-12-22 08:15:55 · 410 阅读 · 0 评论 -
java 为什么使用多线程
多线程用于堆积处理,就像一个大土堆,一个推土机很慢,那么10个推土机一起来处理,当然速度就快了,不过由于位置的限制,如果20个推土机,那么推土机之间会产生相互的避让,相互摩擦,相互拥挤,反而不如10个处理的好,所以,多线程处理,线程数要开的恰当,就可以提高效率。1、吞吐量:做WEB,容器帮你做了多线程,但是它只能帮你做请求层面的,简单的说,就是一个请求一个线程(如struts2,是多线程的,每个客户端请求创建一个实例,保证线程安全),或多个请求一个线程,如果是单线程,那只能是处理一个用户的请求。原创 2023-12-22 08:14:42 · 558 阅读 · 0 评论 -
静态代理和动态代理的区别,什么场景使用
代理是一种常用的设计模式,目的是:为其他对象提供一个代理以控制对某个对象的访问, 将两个类的关系解耦。代理类和委托类都要实现相同的接口,因为代理真正调用的是委托类的方法。由程序员创建或是由特定工具生成,在代码编译时就确定了被代理的类是哪 一个是静态代理。静态代理通常只代理一个类;(2)给 Proxy 类提供 ClassLoader 和代理接口类型数组创建动态代理类;动态代理代理的是一个接口 下的多个实现类;(4)利用动态代理类的构造函数创建动态代理类对象;(3)利用反射机制得到动态代理类的构造函数;原创 2023-12-17 11:09:02 · 456 阅读 · 0 评论 -
Lambda 的表达式作用域(Lambda Scopes)
我们可以直接在 lambda 表达式中访问外部的局部变量:但是和匿名对象不同的是,这里的变量可以不用声明为 final,该代码同样正确,不过这里的变量必须不可被后面的代码修改(即隐性的具有 final 的语义)与局部变量相比,我们对 lambda 表达式中的实例字段和静态变量都有读写访问权限。该行为和匿名对象是一致的。无法从 lambda 表达式中访问默认方法。原创 2023-12-17 11:03:14 · 632 阅读 · 0 评论 -
Java 常用集合及特点
HashSet:底层数据结构是哈希表(无序,唯一),通过 hashcode()和 equals()保证元素唯一。底层数据结构是红黑树(唯一,有序),通过自然排序和比较器排序保证元素有序,根据比较返回值是否是 0 来保证元素唯一性。底层数据结构是数组,查询快,增删慢,线程安全,效率低,默认长度为 10,超过会 100%延长,变成 20,浪费空间。底层数据结构是链表和哈希表(FIFO 插入有序,唯一),由链表保证元素有序,由哈希表保证元素唯一。空间换时间,哈希冲突不大的情况下查找数据性能很高。原创 2023-12-16 11:03:51 · 430 阅读 · 1 评论 -
如何使用 Java 的反射
Class.forName(“全限类名”);例如:com.mysql.jdbc.Driver Driver 类已经被加载到 jvm。中,并且完成了类的初始化工作就行了。原创 2023-12-16 10:50:38 · 384 阅读 · 0 评论 -
select、poll、epoll 区别有哪些
epoll 可以理解为 event poll,不同于忙轮询和无差别轮询,epoll 会把哪个流发生了怎样的 I/O 事件通知我们。(复杂度降低到了 O(1)),通过红黑树和双链表数据结构,并结合回调机制,造就了 epoll 的高效,epoll_create(),epoll_ctl()和 epoll_wait() 系统调用。它仅仅知道了,有 I/O 事件发生了,却并不知道是哪那几个流(可能有一个,多个, 甚至全部),我们只能无差别轮询所有流,找出能读出数据,或者写入数据的流,对他们进行操作。原创 2023-12-16 10:43:11 · 469 阅读 · 1 评论 -
String和StringBuffer、StringBuilder的区别
类,在。原创 2023-12-16 10:33:31 · 379 阅读 · 0 评论 -
KMP算法, 什么是KMP算法 ,暴力匹配 ,KMP算法实现
KMP是Knuth、Morris和Pratt首字母的缩写,KMP也是由这三位学者发明(1977年联合发表论文)。KMP主要应用在字符串的匹配,是一个解决模式串在文本串是否出现过,如果出现过,得出最早出现的位置的经典算法。其主要思想是:当出现字符串不匹配时,可以知道之前已经匹配的文本内容,可以利用这些信息避免从头再去匹配,从而提高匹配效率。因此如何记录已经匹配的文本内容,才是KMP的重点~这也使得next数组派上了用场。KMP算法。原创 2023-12-16 10:11:26 · 1099 阅读 · 0 评论 -
使用Java实现汉诺塔问题
移完这些金片需要 5845.54 亿年以上,太阳系的预期寿命据说也就是数百亿年。真的过了 5845.54 亿年,地球上的一切生命,连同梵塔、庙宇等,都早已经灰飞烟灭。大梵天命令婆罗门把圆盘从下面开始按大小顺序重新摆放在另一根柱子上。并且规定,在小圆盘上不能放大圆盘,在三根柱子之间一次只能移动一个圆盘。大梵天创造世界的时候做了三根金刚石柱子,在一根柱子上从下往上按照大小顺序摞着。2、如果盘子的数量 n >= 2,我就可以看做是两个盘子。1、如果只有一个盘,直接可以A->C。把B塔的所有盘从B->C。原创 2023-12-10 11:19:08 · 393 阅读 · 2 评论 -
使用Java实现基数排序算法
(2)排序过程:将所有待比较数值(正整数)统一为同样的数位长度,数位较短的数前面补零。然后,从最低位开始,依次进行一次排序。这样从最低位排序一直到最高位排序完成以后,数列就变成一个有序序列。(1)基本思想:将整数按位数切割成不同的数字,然后按每个位数分别比较。原创 2023-12-10 11:16:22 · 575 阅读 · 1 评论 -
使用Java实现桶排序算法
把数组 arr 划分为 n 个大小相同子区间(桶),每个子区间各自排序,最后合并。计数排序是桶排序的一种特殊情况,可以把计数排序当成每个桶里只有一个元素的情况。原创 2023-12-10 11:15:09 · 672 阅读 · 1 评论 -
Java实现归并排序算法
(1)基本思想:归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,每个子序列是有序的。然后再把有序子序列合并为整体有序序列。(2)归并排序:是建立在归并操作上的一种有效,稳定的排序算法。原创 2023-12-09 10:28:50 · 493 阅读 · 2 评论 -
Java实现希尔排序算法
(1)基本思想:先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序。原创 2023-12-09 10:27:56 · 403 阅读 · 0 评论 -
Java实现快速排序算法
(1)概念:快速排序是指通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序。整个排序过程可以递归进行,以此达到整个数据变成有序序列。选择一个关键值作为基准值。比基准值小的都在左边序列(一般是无序的),比基准值大的都在右边(一般是无序的)。原创 2023-12-09 10:27:19 · 570 阅读 · 1 评论 -
Java实现插入排序算法
插入排序就类似于斗地主时,整理扑克牌的情况。第一次摸牌时,左收是空的,之后每次摸牌插入到左手的牌时,都会将这张牌和左手中已经排好序的牌,从右到左比较,确认这张牌该放的位置。:通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应的位置并插入。原创 2023-12-09 10:26:41 · 389 阅读 · 0 评论 -
Java实现插入排序算法
插入排序就类似于斗地主时,整理扑克牌的情况。第一次摸牌时,左收是空的,之后每次摸牌插入到左手的牌时,都会将这张牌和左手中已经排好序的牌,从右到左比较,确认这张牌该放的位置。:通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应的位置并插入。原创 2023-12-09 10:24:21 · 418 阅读 · 0 评论 -
java实现冒泡排序算法
对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。如果第一个比第二个大,就交换他们两个。针对所有的元素重复以上的步骤,除了最后一个。原创 2023-12-09 10:23:43 · 618 阅读 · 0 评论