
java
文章平均质量分 83
Java道哥
汲取 传承 打造开源影响力
展开
-
【有料】面试官:来!聊聊线程池的实现原理以及使用时的问题
无论是在工作中,还是在书本中,我们都可以听到或者看到关于线程在使用时的一些建议:不要在代码中自己直接创建线程,而是通过线程池的方式来使用线程。使用线程池的理由大致可以总结为以下几点。1.降低资源消耗。线程是操作系统十分宝贵的资源,当多个人同时开发一个项目时,在互不知情的情况下,都自己在代码中创建了线程,这样就会导致线程数过多,而且线程的创建和销毁,在操作系统层面,需要由用户态切换到内核态,这是一个费时费力的过程。而使用线程池可以避免频繁的创建线程和销毁线程,线程池中线程可以重复使用。2.提高响应速度。转载 2023-04-16 17:22:06 · 223 阅读 · 0 评论 -
cron表达式详解
其中每个元素可以是一个值(如6),一个连续区间(9-12),一个间隔时间(8-18/4)(/表示每隔4小时),一个列表(1,3,5),通配符。(4)/:表示起始时间开始触发,然后每隔固定时间触发一次,例如在Minutes域使用5/20,则意味着5分钟触发一次,而25,45等分别触发一次.(6)L:表示最后,只能出现在DayofWeek和DayofMonth域,如果在DayofWeek域使用5L,意味着在最后的一个星期四触发。例如:在Minutes域使用5,20,则意味着在5和20分每分钟触发一次。转载 2023-01-05 16:05:17 · 159 阅读 · 0 评论 -
Spring国际化i18n
国际化也称作i18n,其来源是英文单词 internationalization的首末字符i和n,18为中间的字符数。由于软件发行可能面向多个国家,对于不同国家的用户,软件显示不同语言的过程就是国际化(举个例子,人们玩的电子游戏,通常可以选择多个语言版本,适应于多个国家的玩家)。通常来讲,软件中的国际化是通过配置文件来实现的,假设某个软件要支撑两种语言,那么就需要两个版本的配置文件。实现国际化,归根结底就是根据语言类型去定义好字符串模板而已。下表列举了一些常见国家、地区的语言编码:国家/地区。转载 2022-11-22 14:23:54 · 1805 阅读 · 0 评论 -
【有料】Java单例模式的7种写法中,为何用Enum枚举实现被认为是最好的方式?
前言如果看到标题就能表示赞同的小伙伴,那估摸你也肯定看过大神说过的这么一句话:。我把它翻译成人话就是:实现单例模式的最佳方法是使用枚举。单例模式单例模式(Singleton Pattern):确保一个类一个实例,并提供一个全局访问点。在开发中,很多时候有一些对象其实我们只需要一个,例如:、、、、等等,这个时候把它设计为单例模式是最好的选择。Java中单例模式是一种广泛使用的设计模式,单例模式有很多好处,它能够避免实例对象的重复创建,不仅可以减少每次创建对象的时间开销,还可以节约内存空间(比如spring管理转载 2022-10-27 00:06:57 · 643 阅读 · 0 评论 -
JVM中的[Ljava.lang.Object; 究竟是什么意思?
这就是表示一个方法,方法有三个参数,类型分别为I,D,L。然后L类型要跟具体的类型,然后以"/"替换包名的".",L类型的要以“;先来简单的说一下, "["表示数组,后面跟着的是具体的类型。你是不是经常看到控制台输出如题的日志,而似懂非懂的。今天我们就来介绍下这些L啦究竟是些什么东东。大多是基本类型的首字母大写,转载 2022-10-23 05:08:03 · 2944 阅读 · 0 评论 -
【有料】调试排错 - Java 问题排查之工具单
著作权归https://pdai.tech所有。Java 在线问题排查主要分两篇:本文是第二篇,通过java调试/排查工具进行问题定位。@pdai。转载 2022-10-10 20:18:51 · 169 阅读 · 0 评论 -
【有料】为什么Synchronized不可中断?
不可中断的意思是等待获取锁的时候不可中断,拿到锁之后可中断,没获取到锁的情况下,中断操作一直不会生效。得到一个解释说,中断操作只是给线程的一个建议,最终怎么执行看线程本身的状态,那么什么状态做什么事情呢?首次尝试获取锁之前就会判断是否应该中断,如果没有获取到锁,在自旋等待的时候也会继续判断中断状态。锁此时为轻量级锁或重量级锁,此时等待线程是在自旋运行或者已经是重量级锁导致的阻塞状态了(非调用了。等方法的阻塞),只把中断状态设为true,没有抛出异常真正中断。可中断呢(未获取到锁也可中断),但是必须使用。转载 2022-10-08 19:25:07 · 1084 阅读 · 0 评论 -
【有料】多个线程分别顺序交替打印一种不同字符ABCDEFG(已实现随便多少个线程打印多少个字符,利用线程池实现多线程)
取消正在执行的线程(实际上仅仅是设置正在执行线程的中断标志位,调用线程的 interrupt 方法来中断线程)。3秒后,主线程调用shutdownNow,这里主要是为了将正在运行的线程设置中断标志位,死循环利用中断标志位结束循环,或线程调用了等待方法(如wait)会抛出异常InterruptException未被捕获而停止。也可利用取余运算%判断线程需要打印的字符,不用生成多个 Condition对象,可利用一个Condition对象,而且可以改变,随便多少个线程打印多少个字符。转载 2022-09-15 00:41:17 · 156 阅读 · 0 评论 -
ThreadLocal的内存泄露?什么原因?如何避免?
在分析ThreadLocal导致的内存泄露前,需要普及了解一下内存泄露、强引用与弱引用以及GC回收机制,这样才能更好的分析为什么ThreadLocal会导致内存泄露呢?更重要的是知道该如何避免这样情况发生,增强系统的健壮性。由于Thread中包含变量ThreadLocalMap,因此ThreadLocalMap与Thread的生命周期是一样长,如果都没有手动删除对应key,都会导致内存泄漏。但是使用弱引用。转载 2022-09-08 15:54:26 · 3342 阅读 · 1 评论 -
【有料】ThreadLocal 内存泄漏问题深入分析
ThreadLocal 基本用法本文就不介绍了,如果有不知道的小伙伴可以先了解一下,本文只研究 ThreadLocal 内存泄漏这一问题。转载 2022-09-08 15:37:23 · 226 阅读 · 0 评论 -
【有料】java中排序函数sort()使用,Arrays.sort()和Collections.sort()
Java中常用的数组或集合排序的方法有两个,一个是java.util.Arrays中的静态方法Arrays.sort(),还有一个是java.util.Collections中的静态方法的Collections.sort()方法,下面分别介绍两种用法。一.java.util.Arrays中的静态方法Arrays中的sort()方法主要是针对各种数据类型(基本数据类型和引用对象类型)的数组元素排序。.......转载 2022-09-04 15:06:41 · 772 阅读 · 0 评论 -
【有料】Java线程池实现原理及其在美团业务中的实践
线程池(Thread Pool)是一种基于池化思想管理线程的工具,经常出现在多线程服务器中,如MySQL。线程过多会带来额外的开销,其中包括创建销毁线程的开销、调度线程的开销等等,同时也降低了计算机的整体性能。线程池维护多个线程,等待监督管理者分配可并发执行的任务。这种做法,一方面避免了处理任务时创建销毁线程开销的代价,另一方面避免了线程数量膨胀导致的过分调度问题,保证了对内核的充分利用。而本文描述线程池是JDK中提供的ThreadPoolExecutor类。降低资源消耗。...转载 2022-08-12 11:20:52 · 245 阅读 · 0 评论 -
【有料】java项目中的classpath到底是什么
在java项目中,你一定碰到过classpath,通常情况下,我们是用它来指定配置/资源文件的路径。在刚开始学习的时候,自己也糊里糊涂,但是现在,是时候弄清楚它到底是指什么了。顾名思义,classpath就是class的path,也就是类文件(*.class的路径)。一谈到文件的路径,我们就很有必要了解一个java项目(通常也是web项目)它在真正运行时候,这个项目内部的目录、文件的结构;这样,我们才好分析、理解classpath。下面,我以一个ssm的项目为例,我先把开发时候的项目的目录结构图放出来。根据转载 2022-07-13 00:25:58 · 378 阅读 · 0 评论 -
Java中System.setProperty()用法
/* * 设置指定键对值的系统属性 * setProperty (String prop, String value); * * 参数: * prop - 系统属性的名称。 * value - 系统属性的值。 * * 返回: * 系统属性以前的值,如果没有以前的值,则返回 null。 * * 抛出: * SecurityException - 如果安全管理器存在并且其 checkPermission 方法不允许设置指定属性。 * NullPointerException - 如转载 2022-07-06 01:49:45 · 550 阅读 · 0 评论 -
【有料】深入剖析LongAdder是咋干活的
LongAdder是JDK8添加到JUC中的。它是一个线程安全的、比Atomic*系工具性能更好的"计数器"。它提供的方法主要有下面这些: LongAdder本身没有成员变量,其值的变更实际上是由父类Striped64管理的。Striped64通过两个成员变量来管理value,分别是base和cells,cells是一个数组,其元素是Striped64的内部类Cell的实现,Cell很简单,只记录一个value。当LongAdder不存在并发访问的时候,会直接通过cas的方式更新base的值,存在并发访问转载 2022-06-30 21:33:50 · 146 阅读 · 0 评论 -
java8 小技巧保证分组groupingBy后排序不变
问题:遇到一个小问题,查询出来一组数据后,按照其中的属性进行groupBy 分组 ,分组后要保证顺序不变。但是实际用groupBy进行分组后,返回的数据是杂乱无章的,没有按照原来list 的顺序返回排查首先去api中查找解决,查看Java 的 java.util.stream 包 Collectors 类 groupingBy 方法实现,结果如下://一个参数 public static Collector groupin...转载 2022-06-21 16:38:48 · 2820 阅读 · 0 评论 -
【有料】Java学习笔记—— finalize() 方法
1、垃圾回收2、finalize()的定义和作用3、finalize()的隐藏问题4、finalize()方法的一般格式5、finalize()的执行过程(生命周期)6、实例1、垃圾回收Java的垃圾回收器只会释放由我们new出来的内存堆块,那些不是由new出来的“特殊内存”,垃圾回收器是不会管理的。 所谓的特殊内存指通过JNI用C/C++向系统申请的内存,这些内存如果不手动去清除就会一直占据在内存中。 而且,垃圾回收本身就有开销,所以虚拟机不会经常GC,只有当内存快要耗尽的转载 2022-05-30 15:49:07 · 265 阅读 · 0 评论 -
【有料】线程中断:Thread类中interrupt()、interrupted()和 isInterrupted()方法详解
首先看看官方说明:interrupt()方法其作用是中断此线程(此线程不一定是当前线程,而是指调用该方法的Thread实例所代表的线程),但实际上只是给线程设置一个中断标志,线程仍会继续运行。interrupted()方法作用是测试当前线程是否被中断(检查中断标志),返回一个boolean并清除中断状态,第二次再调用时中断状态已经被清除,将返回一个false。isInterrupted()方法作用是只测试此线程是否被中断 ,不清除中断状态下面我们进..转载 2022-05-25 15:43:00 · 2356 阅读 · 0 评论 -
【有料】理解Java的强引用、软引用、弱引用和虚引用
前言Java执行GC判断对象是否存活有两种方式其中一种是引用计数。引用计数:Java堆中每一个对象都有一个引用计数属性,引用每新增1次计数加1,引用每释放1次计数减1。在JDK 1.2以前的版本中,若一个对象不被任何变量引用,那么程序就无法再使用这个对象。也就是说,只有对象处于(reachable)可达状态,程序才能使用它。从JDK 1.2版本开始,对象的引用被划分为4种级别,从而使程序能更加灵活地控制对象的生命周期。这4种级别由高到低依次为:强引用、软引用、弱引用和虚引用。转载 2022-05-22 00:35:12 · 117 阅读 · 0 评论 -
什么是HotSpot VM & 深入理解Java虚拟机 JVM
另外,这篇文章也是从一个系列中得出的:《深入理解Java虚拟机:JVM高级特性与最佳实践(第2版)》http://book.2cto.com/201306/25426.html已经下载了这本书(60多M。。)/Users/baidu/Documents/Data/Interview/JavaHotSpot提起HotSpot VM,相信所有Java程序员都知道,它是Sun JDK和OpenJDK中所带的虚拟机,也是目前使用范围最广的Java虚拟机。但不一定所有人都知道的是,这个目前.转载 2022-05-20 10:39:52 · 288 阅读 · 0 评论 -
【有料】HashMap源码解读——逐句分析resize方法的实现
一、前言 最近在阅读HashMap的源码,已经将代码基本过了一遍,对它的实现已经有了一个较为全面的认识。今天就来分享一下HashMap中比较重要的一个方法——resize方法。我将对resize方法的源代码进行逐句的分析。 若想要看懂这个方法的源代码,首先得对HashMap的底层结构和实现有一个清晰的认识,若不清楚的,可以看看我之前写的一篇博客,这篇博客对HashMap的底层结构和实现进行了一个比较清晰和全面的讲解,同时博客的最底下附上了两篇阿里架构师对HashMap的分析,写的非常好,很有参考转载 2022-05-18 13:05:34 · 453 阅读 · 1 评论 -
【有料】厉害了,原来 Redisson 这么好用
本文由 yanglbme 原创,首发于公众号“Doocs开源社区”,欢迎转载。Redis 是最流行的 NoSQL 数据库解决方案之一,而 Java 是世界上最流行(注意,我没有说“最好”)的编程语言之一。虽然两者看起来很自然地在一起“工作”,但是要知道,Redis 其实并没有对 Java 提供原生支持。相反,作为 Java 开发人员,我们若想在程序中集成 Redis,必须使用 Redis 的第三方库。而 Redisson 就是用于在 Java 程序中操作 Redis 的库,它使得我们可以在程序中.转载 2022-05-09 23:05:39 · 395 阅读 · 0 评论 -
学习使用Guava Retryer
一、引入 在平时的开发工作中,重试机制,是一个很重要的逻辑,比如调用其他服务时,如果出现超时,那么可以等100毫秒后再进行调用,或者出现异常时,需要重试;可以重试多次,也可以重试1次,这个都是可以在程序中设定的。 实现上面的逻辑,最简单的方式就是使用for循环了,示例如下: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17转载 2022-03-21 23:24:17 · 472 阅读 · 0 评论 -
【有料】CompletableFuture 使用详解
1、 runAsync 和 supplyAsync方法CompletableFuture 提供了四个静态方法来创建一个异步操作。public static CompletableFuture<Void> runAsync(Runnable runnable)public static CompletableFuture<Void> runAsync(Runnable runnable, Executor executor)public static <U>转载 2022-03-20 00:23:55 · 913 阅读 · 0 评论 -
【有料】使用CompletableFuture
使用Future获得异步执行结果时,要么调用阻塞方法get(),要么轮询看isDone()是否为true,这两种方法都不是很好,因为主线程也会被迫等待。从Java 8开始引入了CompletableFuture,它针对Future做了改进,可以传入回调对象,当异步任务完成或者发生异常时,自动调用回调对象的回调方法。我们以获取股票价格为例,看看如何使用CompletableFuture:// CompletableFutureimport java.util.concurrent.Comple转载 2022-03-19 01:17:22 · 212 阅读 · 0 评论 -
【有料】使用Future
在执行多个任务的时候,使用Java标准库提供的线程池是非常方便的。我们提交的任务只需要实现Runnable接口,就可以让线程池去执行:class Task implements Runnable { public String result; public void run() { this.result = longTimeCalculation(); }}Runnable接口有个问题,它的方法没有返回值。如果任务需要一个返回结果,那么只能保存到变转载 2022-03-19 01:14:06 · 90 阅读 · 0 评论 -
【有料】讲讲Java8的Optional类
前言Java 8中引入了Optional类来解决NullPointerException与繁琐的null检查,该类首次出现在Guava。Java 8 才成为类库中的一部分。入门Optional是一个封装值的类,用于保存类型为T的值;本质上,Optional就是一个容器。举例来说,一个人可能有车也可能没有,那么Person类内部car变量就不应该声明为Car,当变量存在时,Optional类只是对Car的简单封装。变量不存在时,会使用Optional.e...转载 2022-03-18 16:59:17 · 332 阅读 · 0 评论 -
Java集合之LinkedHashMap
一、初识LinkedHashMap上篇文章讲了HashMap。HashMap是一种非常常见、非常有用的集合,但在多线程情况下使用不当会有线程安全问题。大多数情况下,只要不涉及线程安全问题,Map基本都可以使用HashMap,不过HashMap有一个问题,就是迭代HashMap的顺序并不是HashMap放置的顺序,也就是无序。HashMap的这一缺点往往会带来困扰,因为有些场景,我们期待一个有序的Map。这个时候,LinkedHashMap就闪亮登场了,它虽然增加了时间和空间上的开销,但是通过维护转载 2022-02-14 14:58:51 · 480 阅读 · 0 评论 -
Dubbo的多种序列化算法(含transient 关键字在dubbo序列化的使用、作用)
RPC 框架需要通过网络通信实现跨 JVM 的调用。既然需要网络通信,那就必然会使用到序列化与反序列化的相关技术,Dubbo 也不例外。1 JDK序列化操作1.1 实现 Serializable 接口被序列化对象实现 Serializable 接口。public class Student implements Serializable { private static final long serialVersionUID = 1L; private Strin转载 2022-02-07 15:10:19 · 962 阅读 · 0 评论 -
Java transient关键字使用小记
哎,虽然自己最熟的是Java,但很多Java基础知识都不知道,比如transient关键字以前都没用到过,所以不知道它的作用是什么,今天做笔试题时发现有一题是关于这个的,于是花个时间整理下transient关键字的使用,涨下姿势~~~好了,废话不多说,下面开始:1. transient的作用及使用方法 我们都知道一个对象只要实现了Serilizable接口,这个对象就可以被序列化,java的这种序列化模式为开发者提供了很多便利,我们可以不必关系具体序列化的过程,只要这个类实现了Serili...转载 2022-02-07 15:05:21 · 125 阅读 · 0 评论 -
【有料】动态代理
我们来比较Java的class和interface的区别:可以实例化class(非abstract); 不能实例化interface。所有interface类型的变量总是通过某个实例向上转型并赋值给接口类型变量的:CharSequence cs = new StringBuilder();有没有可能不编写实现类,直接在运行期创建某个interface的实例呢?这是可能的,因为Java标准库提供了一种动态代理(Dynamic Proxy)的机制:可以在运行期动态创建某个interfac转载 2021-12-08 13:14:23 · 78 阅读 · 0 评论 -
为什么阿里巴巴禁止开发人员使用isSuccess作为变量名
简介:在定义一个布尔类型的变量,尤其是一个给外部提供的接口返回值时,要使用success来命名,阿里巴巴Java开发手册建议使用封装类来定义POJO和RPC返回值中的变量。但是这不意味着可以随意的使用null,我们还是要尽量避免出现对null的处理的。在日常开发中,我们会经常要在类中定义布尔类型的变量,比如在给外部系统提供一个RPC接口的时候,我们一般会定义一个字段表示本次请求是否成功的。关于这个”本次请求是否成功”的字段的定义,其实是有很多种讲究和坑的,稍有不慎就会掉入坑里,作者在很久之前就遇到.转载 2021-11-02 09:53:36 · 106 阅读 · 0 评论 -
Java对象创建之new关键字和newinstance()方法
new和newinstance()区别 在初始化一个类,生成一个实例的时候,newInstance()方法和new关键字除了一个是方法,一个是关键字外,最主要有什么区别?它们的区别在于创建对象的方式不一样,前者newInstance()是使用类加载机制,后者new关键字是创建一个新类。那么为什么会有两种创建对象方式?这主要考虑到软件的可伸缩、可扩展和可重用等软件设计思想。 Java中工厂模式经常使用newInstance()方法来创建对象,因此从为什么要使用工厂模式上可以找到具体答案。 例...转载 2021-10-22 14:27:08 · 4026 阅读 · 0 评论 -
高级开发必须理解的Java中SPI机制
本文通过探析JDK提供的,在开源项目中比较常用的Java SPI机制,希望给大家在实际开发实践、学习开源项目提供参考。1 SPI是什么SPI全称Service Provider Interface,是Java提供的一套用来被第三方实现或者扩展的API,它可以用来启用框架扩展和替换组件。整体机制图如下:Java SPI 实际上是“基于接口的编程+策略模式+配置文件”组合实现的动态加载机制。系统设计的各个抽象,往往有很多不同的实现方案,在面向的对象的设计里,一般推荐模块之间基于.转载 2021-10-20 17:28:16 · 122 阅读 · 0 评论 -
【干货】dubbo源码阅读——Extension扩展机制
dubbo不仅功能强大,扩展性也非常强,在关键的位置,dubbo都留有扩展接口,比如:协议(Protocol)、集群策略(Cluster)、代理工厂(ProxyFactory)、序列化方式(Serialization)、线程池(ThreadPool)、负载均衡(LoadBalance)等等。每一种扩展都有多种实现,采用策略模式把实现写在/META-INF/dubbo/internal中,然后通过ExtensionLoader类来加载扩展,最终通过一系列的策略选择最正确的那个。这一系列的策略正是今天所讲的内容转载 2021-09-28 11:40:33 · 449 阅读 · 0 评论 -
不可不说的Java“锁”事
前言Java提供了种类丰富的锁,每种锁因其特性的不同,在适当的场景下能够展现出非常高的效率。本文旨在对锁相关源码(本文中的源码来自JDK 8和Netty 3.10.6)、使用场景进行举例,为读者介绍主流锁的知识点,以及不同的锁的适用场景。Java中往往是按照是否含有某一特性来定义锁,我们通过特性将锁进行分组归类,再使用对比的方式进行介绍,帮助大家更快捷的理解相关知识。下面给出本文内容的总体分类目录:1. 乐观锁 VS 悲观锁乐观锁与悲观锁是一种广义上的概念,体现了看待线程同步的不同角度。转载 2021-09-17 14:59:46 · 183 阅读 · 0 评论 -
Java中的自旋锁
自旋锁(spinlock):是指当一个线程在获取锁的时候,如果锁已经被其它线程获取,那么该线程将循环等待,然后不断的判断锁是否能够被成功获取,直到获取到锁才会退出循环。获取锁的线程一直处于活跃状态,但是并没有执行任何有效的任务,使用这种锁会造成busy-waiting。Java如何实现自旋锁?下面是个简单的例子: public class SpinLock { private AtomicReference<Thread> cas = new AtomicR.转载 2021-09-15 14:29:33 · 2724 阅读 · 0 评论 -
什么是线程阻塞?为什么会出现线程阻塞?
什么是线程阻塞?在某一时刻某一个线程在运行一段代码的时候,这时候另一个线程也需要运行,但是在运行过程中的那个线程执行完成之前,另一个线程是无法获取到CPU执行权的(调用sleep方法是进入到睡眠暂停状态,但是CPU执行权并没有交出去,而调用wait方法则是将CPU执行权交给另一个线程),这个时候就会造成线程阻塞。为什么会出现线程阻塞?1.睡眠状态:当一个线程执行代码的时候调用了sleep方法后,线程处于睡眠状态,需要设置一个睡眠时间,此时有其他线程需要执行时就会造成线程阻塞,而且sleep方转载 2021-09-14 22:09:48 · 1433 阅读 · 0 评论 -
用ATOMICSTAMPEDREFERENCE解决ABA问题
在运用CAS做Lock-Free操作中有一个经典的ABA问题:线程1准备用CAS将变量的值由A替换为B,在此之前,线程2将变量的值由A替换为C,又由C替换为A,然后线程1执行CAS时发现变量的值仍然为A,所以CAS成功。但实际上这时的现场已经和最初不同了,尽管CAS成功,但可能存在潜藏的问题,例如下面的例子:现有一个用单向链表实现的堆栈,栈顶为A,这时线程T1已经知道A.next为B,然后希望用CAS将栈顶替换为B:head.compareAndSet(A,B);在T1执行上面这条指令之前转载 2021-09-11 20:04:32 · 234 阅读 · 0 评论 -
浅谈java中的CAS
在JDK 5之前Java语言是靠synchronized关键字保证同步的,这会导致有锁锁机制存在以下问题:(1)在多线程竞争下,加锁、释放锁会导致比较多的上下文切换和调度延时,引起性能问题。(2)一个线程持有锁会导致其它所有需要此锁的线程挂起。(3)如果一个优先级高的线程等待一个优先级低的线程释放锁会导致优先级倒置,引起性能风险。volatile是不错的机制,但是volatile不能保证原子性。因此对于同步最终还是要回到锁机制上来。独占锁是一种悲观锁,synchronized就是一种独占转载 2021-09-11 19:53:36 · 133 阅读 · 0 评论