java 代码优化技巧及原理
合理并谨慎使用多线程
使用场景(I/O阻塞,多CPU并发,多用户并发)
资源争用于同步问题。
java.util.concurrent
启动线程数 = 【任务时间/(任务执行时间-IO等待时间)】*CPU内核数
最佳启动线程数和CPU内核数量成正比,和IO阻塞时间成反比。如果任务都是CPU计算型任务,那么线程数最多不超过CPU内核数,因此启动再多线程,CPU也来不及调度;相反如果是任务需要等待磁锁操作,网络响应,那么多启动线程有助于提高任务并发度,提高系统吞吐能力,改善系统性能。
竞态条件与临界区
在同一程序中运行多个线程本身不会导致问题,问题在于多个线程访问了相同的资源。
当两个线程竞争同一资源时,如果对资源的访问顺序敏感,就称存在竞态条件。导致竞在临界区中使用适当的同步就可以避免竞态条件。
java 线程安全
允许被多个线程安全执行的代码称作线程安全的代码。
方法局部变量
局部变量存储在线程自己的栈中。也就是说,局部变量永远也不会被多个线程共享。所以。基础类型的局部变量是线程安全的。
方法局部的对象引用
如果在某个方法中创建的对象不会逃逸出该方法,那么它就是线程安全的。
对象成员变量
对象成员存储在堆上。如果两个线程同时更新同一个对象的同一个成员,那这个代码就不是线程安全的。
ThreadLocal
既是私有的也是共享的
创建一个ThreadLocal变量(X类静态成员变量):
存储此对象的值(A类a方法):
读取一个ThreadLocal对象的值(B类b方法):
ThreadLocal源码
java 内存泄漏
java 内存泄漏是由于开发人员的错误引起的。
java 中会有逻辑上的内存泄漏
如果程序员保留对永远不再使用的对象的引用,这些对象将会占用并耗尽内存。
长生命周期对象 servlet
静态容器
缓存
合理使用线程池和对象池
复用线程或对象资源,避免在程序的生命周期中创建和删除大量对象。
池管理算法(记录哪些对象是空闲的,哪些对象正在使用)
对象内容清除(ThreadLocal的情空)
池化技术避免了每次都要创建销毁。创建好后放到池子里面去,每次要用的时候取一个出来,用完放回去。Tomcat 自己管理线程池。
使用合适的JDK容器类(顺序表,链表,Hash)
LinkList 和 ArrayList 的区别及适用场景
插入删除链表更好
随机访问数组更好
按照合适额使用场景,可以减少巨大的性能开销。
HashMap 的算法实现及应用场景
使用concurrent包,ConcurrentHashMap和HashMap的线程安全特性有什么不同?
ConcurrentHashMap 分段锁
缩短对象生命周期,加速垃圾回收
减少对象驻留内存的时间
在使用时创建对象,用完释放
创建对象的步骤(静态代码段-静态成员变量-父类构造函数-子内构造函数)
不用的代码等于 null 就会被垃圾回收掉,可能会增加代码复制程度慎用。
使用I/O buffer 及NIO
延迟写与提前读策略
异步无阻塞IO通信
优先使用组合代替继承
减少对象耦合
避免太深的继承层次带来的对象创建性能损失
合理使用单例模式
无状态对象
没有成员对象或者成员对象也是单例
我们现在的 controller service dao 自身也是无状态的,单例的线程安全的,只要按照这个套路写代码,也就不会有线程按全问题。很多人,对线程安全没有什么概念,但是写出来的代码也是线程安全的没有什么问题,这是应为这套是最佳实践。它其实本身就是这种无状态变成的实践,就不会产生线程安全的问题。
领域驱动设计和一些设计模式 更好的变成实践,复制一些,过往的变成实践支撑不起来对这种技术的应用,所以还推广不开。
线程安全
评论