写点什么

9.4Java 代码优化技巧及原理

用户头像
张荣召
关注
发布于: 2020 年 11 月 22 日

1.合理并谨慎使用多线程

使用场景:(I/O阻塞,多CPU并发,多用户并发)

资源争用与同步问题

java.util.concurrent



启动线程数=【任务执行时间/(任务执行时间-IO等待时间)】*CPU内核数

  • 最佳启动线程数和CPU内核数据成正比,和IO阻塞时间成反比。如果任务都是CPU计算型任务,那么线程数量最多不超过CPU内核数,因为启动再多线程,CPU也来不及调度;

            相反如果任务需要等待磁盘操作,网络响应,那么多启动线程有助于提高任务并发度,提高系统吞吐能力,改善系统性能。



2.竞态条件与临界区

在同一程序中运行多个线程本身不会导致问题,问题在于多个线程访问了相同的资源。

当两个线程竞争同一资源时,如果对资源的访问顺序敏感,就称存在竞态条件。

导致竞态条件发生的代码区称作临界区。

在临界区中使用适当的同步就可以避免竞态条件。



3.Java线程安全

允许被多个线程安全执行的代码称作线程安全的代码。

方法局部变量:

  • 局部变量存储在线程自己的栈中。也就是说,局部变量永远也不会被多个线程共享。所以,基础类型的局部变量是线程安全的。

方法局部的对象引用:

  • 如果在某个方法中创建的对象不会逃逸出该方法,那么它就是线程安全的。(不与其他线程共享,仅在线程自己的栈帧中,线程自己访问,栈帧出栈,)

对象成员变量:

  • 对象成员存储在堆上,如果两个线程同时更新同一个对象的同一个成员,那这个代码就不是线程安全的。      



Tomcat多线程编程环境,编码时,大脑中应该有多线程模型。

4.ThreadLocal

 创建一个ThreadLocal变量(X类静态成员变量):

  • public static ThreadLocal myThreadLocal = new ThreadLocal();

存储此对象的值(A类a方法):

  • X.myThreadLocal.set("A thread local value");

读取一个ThreadLocal对象的值(B类b方法):

  • String threadLocalValue=(String)X.myThreadLocal.get();



关键点:ThreadLocal.set源码

public void set(T value){

     Thread t=Thread.currentThread();

     ThreadLocalMap map=getMap(t);

     if(map!=null){

           map.set(this,value);

     }else{

           createMap(t,value);

     }

}



void createMap(Thread t,T firstValued){

     t.threadLocals=new ThreadLocalMap(this,firstValue);

}



5.Java内存泄漏

Java内存泄漏是由于开发人员的错误引起的。



如果程序保留对永远不再使用的对象的引用,这些对象将会占用并耗尽内存。

  • 长生命周期对象

  • 静态容器

  • 缓存

合理使用线程池和对象池:

  • 复用线程或对象资源,避免在程序的生命周期中创建和删除大量对象

  • 池管理算法(记录哪些对象时空闲的,哪些对象正在使用)

  • 对象内容清除(ThreadLocal的清空)

使用合适的JDK容器类(顺序表,链表,Hash)

  • LinkList和ArrayList的区别和使用场景(查询多?增删多?)

  • HashMap的算法实现及应用场景

  • 使用concurrent包,ConcurrentHashMap和HashMap的线程安全特性有什么不同?(HashMap:线程不安全)(ConcurrentHashMap:分段锁:分段并发--保证数据安全)

缩短对象的生命周期,加速垃圾回收:

  • 减少对象驻留内存的时间

  • 在使用时创建对象,用完释放

  • 创建对象的步骤(静态代码段-静态成员变量-父类构造函数-子类构造函数)

public class StaticClass{

      static {

           A a=new A();

      }

      public static void cc(){

           System.out.println("cc()");

      }

}



使用I/O buffer及NIO:

  • 延迟写与提前读策略

  • 异步无阻塞IO通信

使用组合替代继承:

  • 减少对象耦合

  • 避免太深的继承层次带来的对象创建性能损失

合理使用单例模式:

  • 无状态对象

  • 线程安全



用户头像

张荣召

关注

还未添加个人签名 2018.05.02 加入

还未添加个人简介

评论

发布
暂无评论
9.4Java代码优化技巧及原理