
JDK
文章平均质量分 60
WannaRunning
这个作者很懒,什么都没留下…
展开
-
CompletableFuture异步编程实践
CompletableFuture是由Java 8引入的,在Java8之前我们一般通过Future实现异步。CompletableFuture对Future进行了扩展,可以通过设置回调的方式处理计算结果,同时也支持组合操作,支持进一步的编排,同时一定程度解决了回调地狱的问题。原创 2023-03-23 21:02:00 · 358 阅读 · 0 评论 -
Suppiler函数式接口实现优雅的分布式锁
Suppiler接口可以理解为生产者类型接口,生产者的抽象逻辑就是:什么都不用入参,返给外界一个生产出来的对象。Suppiler接口中唯一的get方法用于执行接口实例的方法逻辑,返回指定泛型类型的返回值。所以可以使用这个接口用来包装有返回值的方法。原创 2022-11-11 16:17:41 · 509 阅读 · 0 评论 -
ScheduledThreadPoolExecutor
ScheduledThreadPoolExecutor实现ScheduledExecutorService接口,实现了一些定时任务处理的方法。最常用的调度的两个方法ScheduleAtFixedRate 和 ScheduleWithFixedDelay。原创 2022-10-17 11:48:56 · 293 阅读 · 0 评论 -
Arthas入门使用
Arthas 是一款线上监控诊断产品原创 2022-08-22 15:24:35 · 3488 阅读 · 0 评论 -
Date转LocalDateTime
JDK8后Date类新增了两个LocalDateTime转换相关的方法// Date 获取 Instantpublic Instant toInstant() { return Instant.ofEpochMilli(getTime());}// 使用 Instant 创建 Date public static Date from(Instant instant) { try { return new Date(instant.toEpochMilli()); } catch原创 2022-05-24 15:15:26 · 9758 阅读 · 0 评论 -
String的charAt方法
这个方法可以返回一个String字符串指定索引位置的的char值。String串索引范围是从0到length()-1。String myStr = "Hello";char result = myStr.charAt(0);System.out.println(result); //H原创 2022-05-24 14:38:07 · 2312 阅读 · 0 评论 -
Guava Cache缓存
Google开源的Guava项目中提供了Cache接口和多种本地缓存实现类如LocalLoadingCache,另外,其实之前写的Caffeine缓存的实现就是受到了Guava cache的启发,所以两者在api使用上很相似。LocalLoadingCache的使用假设我们系统中有一个信息来源表,有好多地方需要这个基础数据,所以就打算使用缓存来提升这个接口的性能。缓存方案:新数据被访问到后放在Guava缓存中并设置过期时间,下次访问时如果缓存中有就取缓存,缓存过期就重新查询db后放入缓存。原创 2022-04-09 23:48:22 · 2711 阅读 · 0 评论 -
从CMS垃圾回收器分析常用的垃圾回收算法
CMS 的全称是 Mostly Concurrent Mark and Sweep Garbage Collector(主要并发标记清除垃圾收集器),它在年轻代使用复制算法,而对老年代使用标记-清除算法。那这种回收器有什么优点和缺点,为什么不同代使用不同算法?下面来了解一下标记(Mark)垃圾回收的第一步,就是找出活跃的对象;根据 GC Roots 遍历所有的可达对象,这个过程,就叫作标记。绿色的代表 GC Roots,红色的代表可以追溯到的对象;可以看到标记之后,仍然有多个灰色原创 2021-11-05 20:48:25 · 2277 阅读 · 0 评论 -
从覆盖JDK的类的实现了解打破双亲委派机制的实现
之前的文章写了JVM类加载机制,今天写一下关于如何覆盖JDK中的类的问题。通常情况下,java中提供了endorsed 技术,可以自定义同名的类覆盖jdk中的某些类.比如我们要修改HashMap类,需要将自己的 HashMap 类,打包成一个jar包,然后放到 -Djava.endorsed.dirs 指定的目录中。注意类名和包名,应该和JDK自带的是一样的结构。但是,java.lang 包下面的类除外,因为这些都是特殊保护的。不管有没有同名包类,系统的类加载器永远只是去加载 jre.jar 包中原创 2021-11-04 20:42:40 · 674 阅读 · 0 评论 -
使用ConcurrentHashMap就不需要加锁了么
问:HashMap不是线程安全的,那多线程中可以使用什么代替呢?这个问题想必都会回答,使用ConcurrentHashMap。但是,使用了ConcurrentHashMap就意味着任何操作都不需要加锁就能保证线程安全么?其实不是这样的,ConcurrentHashMap的线程安全指的是ConcurrentHashMap中的put,get方法是线程安全的,也就是说在使用这两个方法时不需要额外加锁。但是这并不意味着其他使用到ConcurrentHashMap的地方都不需要加锁。例如下面的代码:j原创 2021-09-07 21:01:19 · 3857 阅读 · 1 评论 -
JDK8中Map接口下的computeIfAbsent方法
computeIfAbsent方法是java8中新增的方法,该方法用于获取指定key的value值,同时指定当map中没有指定key的value时返回指定的函数式接口中定义的返回值。例如下面一段代码Map<String, List<JobPo>> jobQueueListMap =new HashMap<>();List<JobPo> jobs = jobQueueListMap.get("1001");if(Objects.isNull(job原创 2021-09-02 22:29:46 · 491 阅读 · 0 评论 -
JDK中的延迟队列DelayQueue
JDK中java.util.concurrent包下的DelayQueue是基于过期时间段实现可延迟消费的目的。DelayQueue内部基于可排序的PriorityQueue优先队列来实现的,但是PriorityQueue本身是非线程安全的,所以DelayQueue在实现上通过加ReentrantLock的方式保证线程安全,同时出队和入队都是使用的同一把锁,所以出入队操作不能同时执行。消息入队public class DelayQueue<E extends Delayed> e.原创 2021-09-02 19:03:45 · 515 阅读 · 0 评论 -
JAVA集合取交集或差集操作
记录Set和List两种集合取差集的方法,不需要遍历判断,简单快捷两个Set集合取差集使用com.google.common.collect.Sets类的difference方法。返回两个集合差异的不可修改视图。 返回的集合包含set1包含但set2不包含的所有元素。 set2也可能包含set1不存在的元素; 这些都被忽略了。 返回集合的迭代顺序与set1的迭代顺序匹配。如果set1和set2是基于不同等价关系的集合(如HashSet 、 TreeSet和IdentityHashMap的 k原创 2021-08-27 16:29:48 · 22023 阅读 · 0 评论 -
Clone方法与深拷贝和浅拷贝
如果只是用Object中默认的clone方法实现的只是浅拷贝,虽然是新的对象,但是像String这种引用型变量与原对象中的变量是同一地址。要想在使用clone方法时实现深拷贝,需要实现Java.Lang包下的Clonable接口,重写实现clone方法,方法中调用父类中的clone方法就能得到新的对象。如果类中的成员变量是其他类的引用,那被引用得类也要重写实现clone方法,然后在引用得类的clone方法中调用被引用类的clone方法把被类中的引用变量也clone出来。@Getter@Sett原创 2021-07-27 10:57:10 · 329 阅读 · 0 评论 -
浅谈JDK动态代理的实现
目录JDK动态代理Proxy类InvocationHandler接口JDK动态代理步骤JDK动态代理代码示例JDK动态代理类是如何调用被代理类的方法的JAVA中动态代理分为两种,JDK动态代理和cglib的动态代理。JDK动态代理JDK代理只能对实现接口的类生成代理;在运行时利用反射机制生成一个实现代理接口的匿名类,这样代理类和被代理类就拥有了同样的接口方法,在调用具体方法时通过委托InvokeHandler调用invoke()方法来调用被代理类的方法。Proxy类原创 2021-04-06 14:45:10 · 308 阅读 · 0 评论 -
多线程之ConcurrentHashMap的实现
DK 1.7 中使用分段锁(ReentrantLock + Segment + HashEntry),相当于把一个 HashMap 分成多个段,每段分配一把锁,这样支持多线程访问。锁粒度:基于 Segment,包含多个 HashEntry。 Segment 继承 ReentrantLock(重入锁)用来充当锁的角色,每个 Segment 对象守护每个散列映射表的若干个桶;HashEntry 用来封装映射表的键-值对;每个桶是由若干个 HashEntry 对象链接起来的链表 ...原创 2021-04-02 15:48:54 · 727 阅读 · 1 评论 -
JAVA对象——强引用,弱引用,软引用,虚引用
在Java语言中,除了基本数据类型外,其他的都是指向各类对象的对象引用,称为引用类型。强引用指向对new出来的对象的引用一般就是强引用;当内存空间不足,Java虚拟机宁愿抛出OutOfMemoryError错误,使程序异常终止,也不会随意回收具有强引用的对象来解决内存不足问题。弱引用通过WeakReference类实现,如ThreadLocal中的Entry的实现;弱引用对象存活的生命周期很短,当GC线程扫描时如果发现对象只剩下弱引用了,无论内存是否够用都会把这个对象进行回收。软引用原创 2021-03-22 18:02:01 · 202 阅读 · 0 评论 -
干扰线程执行的前后顺序——Thread类的join方法
经常听到这样一个面试题:如何保证多个线程的执行顺序?答案有很多,比如使用CompletableFuture(JDK8新增),LookSupport工具类,wait和notify,还有这篇文章要写的Thread.join() 方法Thread类的 join() 方法可以阻塞当前的线程,假设线程A中执行调用了线程B的join方法,那在线程B执行完之前,A线程是无法继续往下执行的,需要注意的是 等待调用了join() 方法的线程执行完后再执行,所以使用时不能自己调用自己的join方法,这样会导致线程自身原创 2021-03-20 16:51:43 · 347 阅读 · 1 评论 -
JAVA使用自定义异常的优化——重写fillInStackTrace方法
最近在看性能优化相关的东西,就看到了关于自定义业务异常的使用,观点是不建议,如果一定要使用,在不需要知道异常堆栈信息的情况下必须重写Throwable的fillInStackTrace()方法,这个方法是native修饰即JVM本地同步方法,native实现是将线程的栈帧信息记录到此 Throwable 对象中,也就是我们看到的发生在哪个类的哪一行代码处等信息。其实开发中很多时候为了省事都直接在Service层直接抛业务异常,controller捕获业务异常封装结果,至少有时候我是这么写的。这种情况建议原创 2021-03-07 15:07:06 · 1520 阅读 · 1 评论 -
JDK和Spring中的SPI机制
SPI(Service Provider Interface)是一种服务提供发现机制,为框架提供良好扩展性的机制。这个机制最大的优点就是无须在代码里指定,进而避免了代码污染,实现了模块的可拔插。JDK的SPI机制在项目的classpath下的META-INF\services目录里创建一个以服务接口命名的文件,内容是实现类的全命名。例如数据库驱动jar包中,文件内容就是oracle.jdbc.OracleDriver这个驱动类Spring的SPI机制项目的classpath下的.原创 2021-01-29 15:56:29 · 277 阅读 · 0 评论 -
CAS原子操作之AtomicStampedReference
java.util.concurrent.atomic包中提供了AtomicBoolean,AtomicInteger,AtomicLong等常见类型的类,这些类通过CAS实现了原子操作,但是这些类都是只针对单一类型的单一变量保证原子操作。如果需要对多个变量同时操作,AtomicReference这个类通过指定泛型的方式可以实现对JAVA类进行原子操作。需要注意的是这些类中都存在ABA问题。AtomicStampedReferenceAtomicStampedReference其实和AtomicRe原创 2021-01-25 10:47:19 · 396 阅读 · 1 评论 -
ReentrantReadWriteLock实现原理
之前写了synchronized和基于AQS实现的ReentrantLock,这篇文章写一下与ReentrantLock类似的ReentrantReadWriteLock。ReentrantReadWriteLock和ReentrantLock一样都在java.util.concurrent包下,通常我们使用ReentrantReadWriteLock的两个内部类ReadLock和WriteLock即读锁和写锁来实现更细粒度的同步功能,读写锁的实现也是基于AQS和CAS实现的,分别用的就是AQS的共原创 2021-01-21 15:54:59 · 202 阅读 · 0 评论 -
synchronized锁的级别和ReentrantLock锁(AQS)
针对并发JAVA中提供了JVM级别的synchronized关键字,除此之外在JUC包下Lock接口也提供了类似的锁机制,例如ReentrantLock可重入锁。synchronizedJVM的关键字,依靠底层机制实现的。synchronized 中的锁是非公平的; synchronized 中的锁是可重入的;ReentrantLockReentrantLock 是 JDK 实现的,在java.util.concurrent.locks 包下。实现方式:ReentrantLo.原创 2021-01-20 16:29:00 · 1293 阅读 · 0 评论 -
浅谈java内存模型和volatile可见性实现原理
之前的文章写了volatile关键字特点及AtomicInteger类的实现,这篇文章分析一下volatile为什么能保证变量在多线程间的可见性。JMM中变量操作的方式在java内存模型中,为了提高处理器的执行速度,规定了所有的变量都存储在主内存中,每条线程还有自己的工作内存,线程的工作内存中保存了该线程中是用到的变量的主内存副本拷贝,线程对变量的所有操作都必须在工作内存中进行,而不能直接读写主内存。不同的线程之间也无法直接访问对方工作内存中的变量,线程间变量的传递均需要自己的工作内存和主存之间进行原创 2021-01-18 14:35:50 · 221 阅读 · 0 评论 -
多线程下集合类的选用
ArrayList,HashMap都是非线程安全的类,因此在多线程中不能使用。那么多线程下如果要使用集合或map类型怎么办呢?当然是有别的替代类,比如HashMap要选用HashTable或ConcurrentHashMap,而ArrayList则要选用Vector或CopyOnWriteArrayList。HashTable和ConcurrentHashMap两者的区别就是HashTable是完全基于synchronized锁实现的同步,而ConcurrentHashMap则是CAS+vola原创 2020-12-28 17:13:46 · 632 阅读 · 0 评论 -
AtomicInteger线程安全(volatile和CAS)
volatilevolatile可以实现变量的可见性,即取值操作是线程安全的,但是变量本身在多线程的情况下仍然不是线程安全的,例如volatile int i;i++;CASCAS英文解释是比较和交换,是cpu底层的源语,是解决共享变量原子性实现方案,它定义了三个变量,内存地址值对应V,期待值E和要修改的值U.在Java中通过调用UnSafe的compareAndSet类似方式调用,底层是c,反编译后操作系统指令是cmpxchg指令。CAS操作经常被用来实现无锁数据结构。在java原创 2020-12-16 15:59:44 · 1029 阅读 · 0 评论 -
递归查询——目录树
逻辑首先遍历目录集合找出getParentId=-1的根目录,然后遍历父目录,设置子目录。获取子目录的这个方法时递归方法:遍历所有目录的getParentId与当前父目录id对比,一致则为该目录的子目录,放入subMenus。等到一层子目录归纳完成后,再遍历subMenus对新的子目录执行递归调用。递归条件如果存在子目录,就再按上面的逻辑查询子目录下的子目录;如果没有子目录了,就返回。public static List<CusMenu> builderTree(L..原创 2020-12-03 18:01:58 · 571 阅读 · 0 评论 -
linux 下安装JDK
1.安装RPM:(有rpm包的情况下)进入rpm包所在目录,执行命令:rpm -i jdk-8u131-linux-x64.rpm具体安装的路径是默认的如果第一步中没有rpm文件,那么就按下面的执行:(等同于安装第一步)1.输入yum list installed |grep java,可以查看CentOS自带的Java环境如果有,在root账号下卸载原有jdk: ...原创 2019-01-14 15:38:05 · 136 阅读 · 0 评论 -
线程基础和多线程创建
进程 : 正在执行的程序称作为一个进程。 进程负责了内存空间的划分。线程: 线程在一个进程 中负责了代码的执行,就是进程中一个执行路径,多线程: 在一个进程中有多个线程同时在执行不同的任务。线程负责了代码 的执行,我们之前没有学过线程,为什么代码可以执行? 运行任何一个java程序,jvm在运行的时候都会创建一个main线程执行main方法中所有代码。一个java应用程序至少有两个线程, 一...原创 2018-06-13 16:54:16 · 401 阅读 · 0 评论 -
ThreadLocal
在多线程并发情况下,有一个共享变量,不同线程设置不同值后,各线程只想获取自己设置的值,如何实现?使用ThreadLocal,通过ThreadLocal实例对象的set方法设置各线程自己的值,通过ThreadLocal实例对象的get方法获取各线程自己设置的值。ThreadLocal实现原理分析set方法的实现逻辑,如果getMap方法获取的ThreadLocalMap类型变量map不等于null,则以当前ThreadLocal对象为key,传入的value值为value存到这个ThreadLoc原创 2020-11-09 17:56:17 · 128 阅读 · 0 评论 -
JVM调优和GC过程分析
方法区:又叫静态区,被所有的线程共享;方法区包含所有的class和static变量;方法区中包含的都是在整个程序中永远唯一的元素,如class,static变量。栈:Java中一个线程一个栈区,每一个栈中的元素都是私有的,不被其他栈所访问。栈有后进先出的特点,栈中的数据大小与生存期都是确定的,缺乏灵活性,但是,存取速度比堆要快,仅次于CPU中的寄存器。java中的8中基本数据类型,局部变量都是...原创 2019-11-18 15:03:27 · 310 阅读 · 0 评论 -
自定义注解
目录什么是注解自定义注解使用注解什么是注解注解是一种能被添加到java代码中的元数据,类、方法、变量、参数和包都可以用注解来修饰。注解对于它所修饰的代码并没有直接的影响。简单地说,就是一种标记,可以在程序代码中的关键节点(类、方法、变量、参数、包)上打上这些标记,然后程序在编译时或运行时可以根据这些标记执行一些特殊操作。例如我们常用的@Component就是用于标识一个bean组件用于启动时初始化bean的。自定义注解@Target(value = {Elemen.原创 2020-10-27 15:19:55 · 426 阅读 · 0 评论 -
ClassLoader——类加载
ClassLoader是类的加载器,用于加载class对象到JVM中。ClassLoader层次结构1.根类加载器(BootStrap ClassLoader)JVM本地代码(c/c++)实现,加载(%JAVA_HOME%\jre\lib)。是Java类加载层次中最顶层的类加载器,负责加载JDK中的核心类库,如:rt.jar、resources.jar、charsets.jar等。2.扩展内加载器(Extension ClassLoader) 主要加载扩展目录下的jar包,%JAVA_.原创 2020-10-26 16:45:37 · 505 阅读 · 0 评论 -
Class.forName()和ClassLoader.loadClass()
文章转自 https://www.cnblogs.com/lgg20/p/12507550.htmlJDBC Driver源码如下,使用Class.forName(classname)这种加载方式,使得类在加载时执行代码中的static静态块static { try { java.sql.DriverManager.registerDriver(new Driver()); } catch (SQLException E) { throw ne..转载 2020-10-08 13:58:00 · 575 阅读 · 0 评论 -
JAVA集合中stream流的使用
List常用的功能1.筛选出指定的对象筛选productCode是001的产品 List<RiskDTO> list=riskDTOList.stream().filter(r->{return r.getProductCode().equals("0001");}).collect(Collectors.toList());2.去重 List<RiskDTO> riskDTOList=riskDTOList.stream().distinct().c原创 2020-08-17 10:54:20 · 1702 阅读 · 0 评论 -
JAVA反射的认识
先说Class对象的几种获取方式(推荐使用第三种方式,依赖性较小)通过实例对象获取 LoginService loginService=new LoginService(); Class<?> loginServiceClass=loginService.getClass();通过类名获得 Class<?> loginServiceClass1=LoginService.class;通过Class的静态方法获得 Class<?> lo.原创 2020-06-25 21:49:45 · 216 阅读 · 0 评论 -
对HashMap的认识
JAVA7中的hashMap:1.当我们new一个HashMap时,这个map的数组个数的初始值设为1<<4,也就是2的4此幂即16个,根据后面初始化的逻辑也可以看得出哈希桶的数值始终是2的N次幂,如果不是则向上取一个2的次幂,即如果在使用构造函数创建时指定为是17个,那就会自动取整为32个。为什么必须是2的n次幂呢,是因为hashMap初始化map的下标(0~(表个数-1))时的实现是 hash & (个数-1),只有当个数是2的n次方的时候,个数-1的值才是1111.原创 2020-06-25 20:06:54 · 247 阅读 · 0 评论