KANG's BLOG

Let's have some fun

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.

OSI七层协议

OSI七层协议 物理层: 将数据转换为可通过物理介质传送的电子信号 相当于邮局中的搬运工人。 数据链路层: 决定访问网络介质的方式。在此层将数据分帧,并处理流控制。本层指定拓扑结构并提供硬件寻址,相当于邮局中的装拆箱工人。 网络层: 使用权数据路由经过大型网络 相当于邮局中的排序工人。 传输层: 提供终端到终端的可靠连接 相当于公司中跑邮局的送信职员。 会话层: 允许用户使用简单易记的名称建立连接 相当于公司中收寄信、写信封与拆信封的秘书。 表示层: 协商数据交换格式 相当公司中简报老板、替老板写信的助理。 应用层: 用户的应用程序和网络之间的接口。 四层交换 通过报文中的目标地址和端口,再加上负载均衡设备设置的服务器选择方式,决定最终选择的内部服务器