Java性能优化
- 最佳线程数=[(线程等待时间+线程消耗CPU时间)/线程消耗CPU时间]xCPU数量
- 降低服务器响应时间RT,减少I/O时间最好(低延迟);提升QPS,优化CPU时间最好(高吞吐量)。
- Java字符串编码比较消耗CPU资源,存储成二进制字节可减少字符编码转换。
- 正则尽量使用Cache或预编译
- JVM多租户可以共享同一个JVM避免多个JVM的内存消耗。(Full GC不是隔离的)
- 单次Minor GC时间更多取决于GC后存活对象的数量,而非Eden区的大小。因为对于虚拟机来说,复制对象的成本要远高于扫描成本。因此如果堆中短期对象很多,那么扩容新生代,单次Minor GC时间不会显著增加。
- 如何选择各分区大小应该依赖应用程序中对象生命周期的分布情况:如果应用存在大量的短期对象,应该选择较大的年轻代;如果存在相对较多的持久对象,老年代应该适当增大。
- 使用Executors创建的线程池底层是使用ThreadPoolExecutor创建的,创建
FixedThreadPool
和SingleThreadPool
时,允许的请求队列长度为Integer.MAX_VALUE,可能会堆积大量的请求
导致内存耗尽OOM;创建CachedThreadPool
时,允许创建的线程数量为Inter.MAX_VALUE,可能会创建大量的线程
导致内存耗尽OOM. - SimpleDateFormat不是线程安全的类,一般是用ThreadLocal封装。JDK8推荐使用线程安全的DateTimeFormatter.
- ThreadLocal变量必须在线程任务运行结束时手动回收,否则容易造成内存泄漏(ThreadLocal临时变量)或导致逻辑问题(常驻ThreadLocal变量)。
- ConcurrentHashMap的底层使用了锁分段技术,使用了多个可重入锁ReentrantLock管理多个HashEntry数组,减少了线程对锁的竞争度,提高了执行效率。JDK8去掉了ReentrantLock,直接使用synchronized Table元素作为锁实现对每一行元素加锁,对长度大于8(默认值)的长列表采用红黑树优化。
- volatile变量的作用:在
多核
CPU环境下,每个CPU都有自己的高速缓存区,使用同一个变量的多个线程进入了多个CPU核心并行,变量被写入到多个高速缓存区,从而导致在一个线程中修改的变量无法同步到其他线程。volatile关键字可以让被修饰的共享变量在转换成汇编语言时,增加一个前缀指令lock,CPU发现这个指令时会先嗅探其他CPU是否有对这个变量修改,若发现缓存无效,则重新从内存中读取。当这个变量写回时,会立即写回到内存,并通知其他内核该地址的高速缓存无效。
参考:
《大型网站技术架构演进与性能优化》
Jvm多租户简介
从实际案例聊聊Java应用的GC优化_美团技术团队
阿里巴巴《Java开发手册手册》
深入分析ConcurrentHashMap的锁分段技术
java8中对ConcurrentHashMap的改进
volatile实现可见性的原理
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 using1174@foxmail.com
文章标题: Java性能优化
文章字数: 814
本文作者: Jun
发布时间: 2019-05-15, 20:24:00
最后更新: 2019-09-11, 20:23:16
原始链接: http://yoursite.com/2019/05/15/Java性能优化/版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。