KANG's BLOG

Let's have some fun

Java中的new关键字

new关键字在生成对象时完成了三件事情: 为对象开辟内存空间。 调用类的构造方法。 将生成的对象的地址返回。 在并发环境下从堆中划分内存空间是非线程安全的 new是原子性操作 new运算符具有数据操作的原子性 也就是说创建一个Java对象分配内存,要么所有步骤都成功,返回对象的引用,要么回归到创建之前的内存状态,返回为NULL。

Java中的多线程

1. 线程状态 初始(NEW):新创建了一个线程对象,但还没有调用start()方法。 RUNNABLE):Java线程中将就绪(ready)和运行中(running)两种状态笼统的成为“运行”。 线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取cpu 的使用权,此时处于就绪状态(ready)。就绪状态的线程在获得cpu 时间片后变为运行中状态(running)。 阻塞(BLOCKED):表线程阻塞于锁。 等待(WAITING):进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)。 超时等待(TIME_WAITING):该状态不同于WAITING,它可以在指定的时间内自行返回。 终止(TERMINATED):表示该线程已经执行完毕。 2.

Java的SPI机制

Java SPI机制 我们系统里抽象的各个模块,往往有很多不同的实现方案,比如日志模块的方案,xml解析模块、jdbc模块的方案等。 面向的对象的设计里,我们一般推荐模块之间基于接口编程,模块之间不对实现类进行硬编码。一旦代码里涉及具体的实现类,就违反了可拔插的原则, 如果需要替换一种实现,就需要修改代码。为了实现在模块装配的时候能不在程序里动态指明,这就需要一种服务发现机制。 Java SPI的约定 当服务的提供者,提供了服务接口的一种实现之后,在jar包的META-INF/services/目录里同时创建一个以服务接口命名的文件。 该文件里就是实现该服务接口的具体实现类。而当外部程序装配这个模块的时候,就能通过该jar包META-INF/services/里的配置文件找到具体的实现类名,并装载实例化,完成模块的注入。 基于这样一个约定就能很好的找到服务接口的实现类,而不需要再代码里制定。 jdk提供服务实现查找的一个工具类:java.

Java线程池原理

一、线城池处理任务的优先级 如果此时线程池中的数量小于corePoolSize,即使线程池中的线程都处于空闲状态,也要创建新的线程来处理被添加的任务。 如果此时线程池中的数量等于corePoolSize,但是缓冲队列 workQueue未满,那么任务被放入缓冲队列。 如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量小于maximumPoolSize,建新的线程来处理被添加的任务。 如果此时线程池中的数量大于corePoolSize,缓冲队列workQueue满,并且线程池中的数量等于maximumPoolSize,那么通过 handler所指定的策略来处理此任务。 核心线程corePoolSize、任务队列workQueue、最大线程maximumPoolSize,如果三者都满了,使用handler处理被拒绝的任务。 二、Handler拒绝策略 ThreadPoolExecutor.AbortPolicy() 抛出java.

Jdk动态代理和CGLib动态代理

区别 jdk的动态代理是基于接口的动态代理,要求目标对象必须实现至少一个接口,核心API是java.lang.reflect.Proxy类的newProxyInstance方法。 Object proxy = Proxy.newProxyInstance( ClassLoader loader, Class[] interfaces, InvocationHandler handler ); cglib的动态代理是基于子类的动态代理,不需要目标对象实现接口,要求被代理类不能由final修饰.

JVM编译过程和优化措施

一、前端编译 前端编译就是将Java源码文件编译成Class文件的过程,编译过程分为4步: 1 准备 初始化插入式注解处理器(Annotation Processing Tool)。 2 解析与填充符号表 将源代码的字符流转变为标记(Token)集合,构造出抽象语法树(AST)。

LoadingCache的使用

介绍 LoadingCache时Guava包中提供的缓存工具,其原理是调用get方法就会调用内部的getOrLoad(K key)方法,缓存中有对应的值则返回,没有则使用CacheLoader的load方法 。getOrLoad(K key)方法为线程安全方法,内部加锁 Maven坐标 <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>27.1-jre</version> </dependency> 如何使用 LoadingCache<Long, String> cache = CacheBuilder.

MapStruct - Java对象转换器

如何干掉BeanUtils? 写业务代码时,为了保证service的复用和逻辑关系,我们通常需要保持良好的分层结构,比如controller -> service -> dao,职责分明,复用性强,但是带来的问题就是频繁的对象转换。 有一种方式就是每两个对象的转化都编写对应的converter方法,方法内部直接新建对象并为其赋值。这样做最大问题就是代码量骤增,虽然我们可以放在assembler中保持service代码干净,但依旧避免不了开发成本高的问题,而且后期DO变化时,项目中所有的converter都需要修改。 还有一种解决方案是BeanUtils的对象复制功能,但它是在运行期通过反射做的对象转换,性能非常差。 有没有一种方法在编译器动态进行对象转化呢? MapStruct介绍 MapStruct是一个在编译器进行代码增强来帮你进行对象转换的工具。

Nginx配置及负载均衡策略

Nginx配置 http { keepalive_timeout 65; upstream upstream_name{ server 192.168.0.28:8001; server 192.

Nginx配置及负载均衡策略

Nginx配置 http { keepalive_timeout 65; upstream upstream_name{ server 192.168.0.28:8001; server 192.