
Java
文章平均质量分 50
多动手,勤思考
阿布
展开
专栏收录文章
- 默认排序
- 最新发布
- 最早发布
- 最多阅读
- 最少阅读
-
使用lambda + Consumer 对一次业务代码的优化
线上业务有一功能,通过订单类型、订单子类型、商家ID查询一个配置。后续又需要拓展一个新功能,即在继续增加 一级类目、二级类目 作为查询条件一起查询,如果二级类目没有配置,以一级类目的配置为准,一级类目如果也没有配置,以最开始的订单类型、订单子类型、商家ID 为准,再没有 那就只能给一个默认值了,这是大致的需求。如果这个接口每次只有单个查询好办,代码只需要如下: public 配置数据 queryOneRecord(BulkConfigKey key) { /.原创 2021-10-22 17:24:47 · 446 阅读 · 0 评论 -
Java opencsv CSVWriter 用excel打开 乱码
在你的流输出前加上三句话即可搞定os.write(0xef); //加上这句话os.write(0xbb); //加上这句话os.write(0xbf); //加上这句话FileOutputStream os = new FileOutputStream(file);os.write(0xef); //加上这句话os.write(0xbb); //加上这句话os.write(0xbf); //加上这句话CSVWriter csvWrite = new CSVWriter(n..原创 2021-07-20 14:10:17 · 1092 阅读 · 0 评论 -
为什么java会有IINC指令
使用ILOAD/SIPUSH/IADD/ISTORE 也可以完成 IINC 的工作,主要是因为IINC是一个单指令,而前者则是4个,从存储空间上来说,可以节省一些空间,在Java解释执行期间,解释一个指令也比解释执行4个指令效率要高些,当使用JIT编译成本地代码执行后,则区别不大了。参考链接:https://stackoverflow.com/questions/37056714/why-does-java-have-an-iinc-bytecode-instruction.原创 2021-07-17 09:34:28 · 1024 阅读 · 0 评论 -
Java输出浮点数不精准表达的最原始的值
通过BigDecimal输出就好:System.out.println(new BigDecimal(0.3));参考:https://stackoverflow.com/questions/22526897/how-does-java-precisely-display-a-double-while-it-cannot-be-accurately-expressed原创 2021-07-08 00:55:35 · 137 阅读 · 0 评论 -
本地jar包部署到私服上
mvn deploy:deploy-file -Dmaven.test.skip=true -DgroupId=你的groupId-DartifactId=你的artifactId-Dversion=你的版本号-Dpackaging=jar(包类型,也可以是pom) -Dfile=你的本地jar地址(注意,最好不要用本地仓库中的路径,拷贝出来使用)-Durl=你的仓库上传地址-DrepositoryId=仓库地址 -DpomFile=你的本地jar对应的pom文件地址(注意,最好不要用.原创 2021-06-18 14:49:18 · 317 阅读 · 0 评论 -
Java BigDecimal将小数无用的0去除
public static void main(String[] args) { System.out.println(new BigDecimal("1.0010").stripTrailingZeros().toPlainString()); }原创 2021-06-18 14:37:12 · 1078 阅读 · 0 评论 -
idea Module must not contain source root. The root already belongs to module
进入 Project Structure,到Modules下,把应该是两个根目录的项目,其中一个从文件夹中右键标记为 excluded 即可原创 2021-06-10 13:41:49 · 253 阅读 · 0 评论 -
Java打印出对象的真实地址
直接使用对象.hashCode()时,可能因为对象重写了hashCode方法,导致两个地址不一样的对象,打印出来的地址是同一个,这时候可以使用System.identityHashCode(对象变量),直接打印出该对象的真实地址。...原创 2021-06-06 15:00:49 · 1656 阅读 · 0 评论 -
为什么二进制整数变负数的时候,需要在反码上 +1
为什么二进制整数变负数的时候,需要在反码上 +1举个例子1的负数是-1,-1 + 1时,结果为0,此时我们用二进制来演算一下,1的二进制是0001,0的二进制是0000,此时将1的二进制进行取反,1110(如果用这个当做-1的二进制会发生什么),如果用1110代表-1,那么+1后,结果应该是0000,也就是10进制中的0,1110 + 1 = 1111当直接用反码进行计算时,发现并不是这么回事,而是变成了1111,而当1111再次进行加1时,由于二进制的进位,所有的1都满足2都变成0,超过原创 2021-06-06 08:08:48 · 2229 阅读 · 0 评论 -
Java三元运算符与拆箱装箱引起的误会
场景一次线上问题,出现了NPE,当时的代码类似如下:1. Map<String, 业务对象> map = xxxService.findXxx(xxx);2. Long result = map.get(xxx) != null ? map.get(xxx).getId() : 0L;就是第二行出错了,正常来说,当map.get(xxx)时,咱已经判断了null了,只有非null才会get呀,怎么还会出现null异常呢?排查问题的过程当中,搜到了这么一篇博客:https://blo原创 2021-05-30 01:09:22 · 806 阅读 · 1 评论 -
Redis Server端太多TIME_WAIT
场景redis服务器端连接产生太多的TIME_WAIT,使用下方的命令统计,高达20000+个状态连接,netstat -na | grep 6379 | grep TIME_WAIT | wc -l排查去查看应用代码中连接redis的方式,发现每次操作都会重新获取一次连接,在操作完毕后则进行close,并没有使用线程池:这种方式肯定会造成大量的连接被创建,但是TIME_WAIT是由发起关闭请求的一方才会有的状态,每次close都是由客户端发起的,怎么会在服务器方呢?通过demo + Wire原创 2021-05-29 17:34:59 · 2565 阅读 · 0 评论 -
Redisson NoClassDefFoundError RedisStreamCommands
高版本jar包的Spring-Redisson中,多出来一个类 RedissonConnection,这个类在jar中不存在,解决方法是换成下面的版本就好了: <dependency> <groupId>org.redisson</groupId> <artifactId>redisson-spring-boot-starter</artifactId> <version>3.11.5</versi原创 2021-05-29 08:56:07 · 1176 阅读 · 0 评论 -
靠谱 Spring Boot与jsp打包成jar|war使用
场景使用 spring boot + html or jsp 组合时 , 目录如下设置视图代码@Configuration@EnableWebMvcpublic class MvcConfiguration implements WebMvcConfigurer, ApplicationContextAware { @Override public void configureViewResolvers(ViewResolverRegistry registry) { Internal原创 2021-05-27 10:08:19 · 1529 阅读 · 1 评论 -
简单聊聊java中为什么重写equals后需要重写hashCode
先看现象public class TestDemo { public static void main(String[] args) { Person p1 = new Person("阿伦"); Person p2 = new Person("阿伦"); System.out.println(p1.equals(p2)); } static class Person { public Person(String原创 2021-05-21 15:31:48 · 384 阅读 · 1 评论 -
Pulsar Consumer 与 线程池搭配使用不当发生的现象问题
场景近日,使用pulsar做削峰,一波3-40条消息,每条消息的平均处理完毕速度在10秒左右,发现吞吐量很慢,根据日志观察,消费者每次在同一秒处理10条消息,等待一分钟后继续处理第2波的十条消息,以此类推,很有规律,每次都是相隔一分钟处理后面的10条信息。解决过程1. 首先观察每条消息所在的线程名称找到消息处理的线程名称,发现比较特殊化,带有页面名称,应该是项目自定义的线程池没错了,随后找到这个线程池的配置,发现核心、最大线程数都是10,这应该符合我们看到上面的每次10条的现象之一了, 同时线程池原创 2021-05-21 12:38:12 · 1971 阅读 · 0 评论 -
连接redis, 因为密码有特殊字符#, 导致无法正常连接
场景使用lettuce-core连接redis时,格式是 redis://[[username :] password@] host [: port] [/ database][? [timeout=timeout[d|h|m|s|ms|us|ns]] [&database=database]] ,由于密码中有一个#号,导致识别出现问题无法连接上redis,解决方式是将密码使用URLEncoder.encode("#")计算一下encode后的字符拿出来使用就行了,例如#号encode后是%原创 2021-04-29 15:13:27 · 7106 阅读 · 0 评论 -
sharding sphere 分多张表不支持 xml 中的批量更新以及解决方式
现象在同一个库中,将一张表分成多张,在xml中使用如下的语法:<foreach collection="params" item="item" separator=";"> update table_hello set column_hello = #{item.itemHello} where sharding_key = #{item.shardingKey}</foreach>PreciseShardingAlgorithm:public String do原创 2021-04-28 14:25:20 · 3487 阅读 · 0 评论 -
CAS与Atomic类
CAS什么是CAS?CAS全称Compare and swap(比较与替换), 该技术用于并发更新一个值数据时,使用不加锁的方式去安全的更新,因为加锁是一种比较昂贵的操作,不加锁又无法保证多线程下的安全性,CAS在赋值时,有三个关键值,预期值新值旧值该操作的原子性由操作系统保证,在赋值时,使用预期值和旧值对比,当这两个值相等时,才将内存中的值替换为新值,否则就失败(和乐观锁同理, 也就可以理解CAS就是一种乐观锁),失败后,通过一个循环的方式(称之为自旋),重新去尝试赋值,直到成功为止,原创 2021-04-05 10:52:07 · 234 阅读 · 2 评论 -
Java多线程(9)-死锁问题、线程安全容器与CAS
线程安全问题看如下代码:private static int globalI = 0;public static void main(String[] args) throws Exception { ExecutorService executorService = Executors.newFixedThreadPool(4); for (int i = 0; i < 1000; i++) { executorService.submit(() ->原创 2021-03-13 15:43:06 · 204 阅读 · 2 评论 -
Java多线程(8)-JMM(Java Memory Model)
JMMJava的内存模型分为栈(stack)和堆(heap), 栈空间是每个线程独有的,每个线程的栈空间中都会有多个方法栈桢,看下面的代码,public static void main(String[] args) { Object a = new Object();}这份代码运行起来后,jvm会启动一个名叫main的线程,同时为该线程分配栈空间,并运行一个名为main的方法栈桢,而这个main方法运行后,栈桢中将会有一个类型为object,名为a的局部私有变量,new Objec原创 2021-03-13 12:02:33 · 216 阅读 · 0 评论 -
Java多线程(7)-多线程的中断与InterruptedException
InterruptedException在我们使用一些线程相关的方法时,例如sleep, 该方法会抛出一个InterruptedException,try { Thread.sleep(1000);} catch (InterruptedException e) { e.printStackTrace();}相关的还有BlockingQueue.put/take等方法, 都会抛出InterruptedException异常,为什么会有这个异常呢?举一个例子,在日常的电脑使用过原创 2021-03-13 08:20:19 · 798 阅读 · 0 评论 -
Java多线程(6)-Runnable与Callable
Runnable 与 Callable是什么?在前面的文章叙述中,有一句很明确的表达,java中只有Thread对象代表一个线程对象,一个线程像一个工人一样,按照我们提供的说明书一句一句的读,并按照说明书说的去做,Runnable 或 Callable 其实就是一份说明书。线程的几种创建方式1.new Thread() { @Override public void run() { try { Thread.sleep(60000); } catch (In原创 2021-03-10 22:35:23 · 501 阅读 · 0 评论 -
Java多线程(5)-ThreadLocal
ThreadLocalThreadLocal一般用于存储当前线程私有的值,和其他线程不共享的值,并且多个线程根据同一个ThreadLocal对象get获取到的就是独属于当前线程的值,与其他线程具有隔离性,它的方便之处就是可以不通过方法参数在方法栈从始至终传递一个或多个参数,而是通过一个共享的变量,类似静态类.方法的方式获取值。自己实现一个ThreadLocal首先,线程数据隔离,如何隔离?我们可以以线程的id作为唯一主键,对应着该id相应的值,由此可以选择使用Map数据结构,用作存储,key是线程原创 2021-03-06 11:15:38 · 412 阅读 · 2 评论 -
Java多线程(4)-Thread的生命周期
Thread的生命周期Java中的Thread类中还有一个内部枚举类STATE, 这个枚举代表了线程从始至终的状态,NEW指一个新创建的线程,还没有开始执行RUNNABLE处于该状态,意味着当前线程正在执行 或者 正在等待执行,甚至可能是在等待IO,这里就会有一个疑问,如果线程在等待IO,难道不应该处于阻塞状态吗?在JVM中,线程的阻塞状态(BLOCKED)用于表示另一种特殊的情况,而当线程调用IO时,发起一个Linux的open系统调用,此时CPU发现该线程要进行IO操作,将会切换执行其原创 2021-03-03 22:41:39 · 203 阅读 · 4 评论 -
Java多线程(3)-Thread的底层模型
Thread的底层模型Thread类中的每一个实例代表JVM中的一个线程。JVM中的线程在Linux上称为轻量级进程, 和进程本质无区别,在Windows上使用系统线程。下面着重说一下在Linux中对应的轻量级进程概念,如下图, 进程和线程一样,都是用于一行一行的执行代码的,唯一的区别就是多个线程可以共享同一个进程的内存空间,而进程之间的内存是隔离开来的。所以在Linux实现中,将进程和线程都称之为task(如下图), 只是可能有些task共享同一块内存空间,称之为进程组(process g原创 2021-03-03 21:45:01 · 319 阅读 · 1 评论 -
Java多线程(2)-Thread
Thread是什么Thread类的每一个实例(调用了start()方法并且未结束)代表一个JVM中的线程,注意Runnable和Callable都不是线程,当Thread.start()后,JVM中就增加了一个工人/执行流(线程)和一套方法栈。如下图,Java的最小执行单元就是方法,每个线程都有一个方法栈,里面有一个个方法栈桢,一个方法执行完毕后,栈桢就销毁,继续执行下面的栈桢,拥有方法栈也证明它是一个存活着的线程,Java中所有方法执行的最底层的方法栈桢,一定是XXX类的main方法或者Thre原创 2021-03-03 12:19:03 · 118 阅读 · 0 评论 -
Java多线程(1)-为什么需要多线程
为什么需要多线程?简单来说, 因为CPU与内存以及IO之间存在着巨大的性能差异。推荐阅读文章 这个世界慢死了 https://zhuanlan.zhihu.com/p/58431253 。CPU运行的时间单位是cycle, 称为时钟周期,一次简单的运算大概在1-2个时钟周期。例如一个3GHz的CPU,意味着每秒可以执行30亿次的时钟周期,也就是大概1纳秒可以执行一次简单的操作。内存的一次寻址时间是1-10微秒, CPU如果等内存一次寻址,就意味着大概要等1000-10000个时钟周期。普通硬盘的原创 2021-02-28 22:06:14 · 1002 阅读 · 0 评论 -
Unable to add module to the current project as it is not of packaging type ‘pom‘
Unable to create project from archetype [org.apache.maven.archetypes:maven-archetype-quickstart:RELEASE]Unable to add module to the current project as it is not of packaging type ‘pom’这个错误是当前目录不是空文件夹,导致无法生成项目,请去一个空文件夹下生成就可以了...原创 2021-01-25 14:51:34 · 194 阅读 · 0 评论 -
Maven Invoker process ended with result different than 0!
出现这个错误时, 注意看下该错误上方的错误信息这里说在仓库存储目录下没有setting.xml文件, 所以我们将maven目录下的conf/setting.xml文件放到仓库存储目录下即可,如下原创 2021-01-25 11:28:50 · 1507 阅读 · 0 评论 -
什么是缓冲区
1. 什么是缓冲区缓冲区又称为缓存,它是内存空间的一部分。也就是说,在内存空间中预留了一定的存储空间,这些存储空间用来缓冲输入或输出的数据,这部分预留的空间就叫做缓冲区。缓冲区根据其对应的是输入设备还是输出设备,分为输入缓冲区和输出缓冲区。2. 为什么要引入缓冲区我们为什么要引入缓冲区呢?比如我们从磁盘里取信息,我们先把读出的数据放在缓冲区,计算机再直接从缓冲区中取数据,等缓冲区的数据取完后再去磁盘中读取,这样就可以减少磁盘的读写次数,再加上计算机对缓冲区的操作大大快于对磁盘的操作,故应用原创 2021-01-24 21:57:46 · 29130 阅读 · 7 评论 -
Java异常体系概述
Java的异常体系结构Java异常体系的根类是 Throwable, 所以当写在java代码中写throw抛出异常时,后面跟的对象必然是Throwable或其子类的对象。其中Exception异常是指一些可以恢复的异常, 例如常见的NullPointerException空指针异常。Error指的是一些致命的错误,无法通过程序代码手段恢复的异常,例如OutOfMemoryError内存溢出错误。unchecked异常在上图中除了RuntimeException、Error及其子类都是属于unch原创 2021-01-04 15:20:06 · 269 阅读 · 0 评论 -
2020-10-10线上问题调查笔记
场景国庆期间,线上微信端系统,出现无法正常使用情况,根据日志排查,出现42001错误码,是redis中存储的accessToken失效,导致系统异常,将redis中缓存的过期accessToken删除后,即恢复正常使用。思考排错首先根据代码层面的观察,获取到token之后,存储的是6000秒,而微信官方文档描述的是,返回的accessToken有效期在7200秒,所以系统缓存中的token一般来说肯定会在微信系统失效前进行失效,但是为什么会发生token在本系统中失效的情况呢。1. 白名单问题原创 2020-10-10 13:09:31 · 371 阅读 · 0 评论 -
ClassNotFoundException: org.apache.commons.pool2.impl.GenericObjectPoolConfig
添加commons-pool2 jar包<dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-pool2</artifactId> <version>2.6.2</version></dependency>原创 2020-10-10 13:08:51 · 1055 阅读 · 0 评论 -
17学Java之Collection体系
什么是Collection首先打开Collection这个类的源代码,查看第一段话 The root interface in the collection hierarchy. A collection represents a group of objects, known as its elements. Some collections allow duplicate elements and others do not. Some are ordered and othe原创 2020-09-12 17:34:58 · 343 阅读 · 0 评论 -
17学Java之Maven Scope
Scope属性scope属性用于控制jar包处于的作用域范围,因为很多情况下我们使用的jar并不需要放入到最终的classpath中以供程序运行中使用,所以可以通过scope属性来控制。test (测试)当scope的值是test时,代表这个jar包只在test编译和test运行时,才存在于classpath当中。例如:当我将spring-boot-starter-web这个jar的scope设置为test的时候,jar包中的org.springframework.web.context.r原创 2020-08-14 13:31:56 · 395 阅读 · 0 评论 -
比较两个“语义化版本“ Java实现
题目要求:请根据语义化版本的要求 https://semver.org/lang/zh-CN/ ,比较两个"语义化版本"传入两个形如x.y.z的字符串,比较两个语义化版本的大小。如果version1小于version2,返回-1;如果version1大于version2,返回1。如果二者相等,返回0。注意,如果传入的字符串形如x,则其等价于x.0.0。 如果传入的字符串形如x.y,则其等价于x.y.0。方法有两个参数:version1 传入的版本字符串1,支持x/x.y/x.y.z,你可以假定传入原创 2020-08-14 09:52:40 · 549 阅读 · 0 评论 -
17学Java之Maven包冲突及解决实战
一般Java开发过程中,包冲突异常提现在下面几个AbstractMethodErrorNoClassDefFoundErrorClassNotFoundExceptionLinkageError像上图,就发生了包引用冲突,如果C包v0.1版本在前,JVM加载过v0.1版本里的同名类后就不会加载v0.2里的同名类,这很可能造成丢失了v0.2里同类里新增的方法属性等等。接下来我们看看Maven对这种情况是如何进行管理的。Maven 对 pom 文件的传递性依赖自动进行管理, 其中有一个原则原创 2020-08-13 13:18:55 · 552 阅读 · 0 评论 -
17学Java之Maven的包管理
没有包管理工具的年代在没有包管理工具的年代, 开发人员只能手动下载编译或者收集好程序开发需要的所有jar包,例如 java -classpath x1.jar; x2.jar; x..10001.jar; com.testJavaApplication如果有一万个jar包,就需要手动指定一万个jar的目录路径等等,还要考虑到其中有没有冲突关系,依赖关系等等。过渡时代Apache Ant手动下载jar包,放在一个目录中。写XML配置,指定编译的源代码目录、依赖的Jar包、输出目录等。缺点原创 2020-08-12 14:14:21 · 842 阅读 · 0 评论 -
17学Java之Java的包原理
从某种层面上来说,JVM的工作非常简单,即:执行一个类的字节码执行一个类的字节码过程中,碰到了一个新的类,加载它的字节码,然后重复第一步例如下面的代码:public class Application { public static void main(String [] args) { 1. 启动main程序的时候加载Application类的字节码 A a = new A(); 2. 碰见A类实例化,加载A类的字节码 a.hello(); B b =原创 2020-08-12 12:14:35 · 680 阅读 · 0 评论 -
Java之Finalize方法
对象生存还是死亡?在可达性分析算法中判定为不可达的对象,也不是"非死不可的"的,这时候它们暂时还处于“缓刑”阶段,要真正宣告一个对象死亡,至少要经历两次标记过程。如果对象在进行可达性分析后发现没有与GC Roots相连接的引用链,那它将会第一次被标记,随后进行一次筛选,筛选的条件是此对象是否有必要执行finalize()方法。 假如对象没有覆盖(实现)finalize()方法,或者finalize()方法已经被虚拟机调用过,那么虚拟机将这两种情况都视为没有必要执行。如果这个对象被判定为确有必要执行fi原创 2020-05-27 10:50:20 · 298 阅读 · 0 评论