J2EE代码优化

J2EE代码优化

  1. 与log4j有关的性能问题

    • Logger变量添加static修饰符
    • 使用transient防止Logger对象序列化
    • 使用log.isDebugEnable()来减少准备形参的开销
  2. 与字符串有关的性能问题

    • 不要使用String中提供的split,replace,replaceAll等方法

    • 替代方案:使用org.apache.commons.lang.StringUtils中提供的split,replaceChars,性能是JDK实现的3-4倍

      split示例:

      public static void main(String[] args) {
          String test = "123,123,123,123,123,123,123,123,123";
      
          for (int i = 0; i < 100000; i++) {
              test = test.concat("123,123,123,123,123,123,123,123,123");
          }
      
          long start = System.currentTimeMillis();
      
          // String[] split = test.split(","); // 44
      
          String[] split = StringUtils.split(test, ',');  // 37
      
          long stop = System.currentTimeMillis();
      
          System.out.println(stop - start);
      }
      

      replace,replaceAll,replaceChars示例

      public static void main(String[] args) {
          String test = "123,123,123,123,123,123,123,123,123";
      
          for (int i = 0; i < 100000; i++) {
              test = test.concat("123,123,123,123,123,123,123,123,123");
          }
      
          long start = System.currentTimeMillis();
      
          // System.out.println(test.replace("123", "456")); // 99
          // System.out.println(test.replaceAll("123", "456"));  // 101
      
          StringUtils.replace(test, "123", "456");  // 44
          StringUtils.replaceChars(test, "123", "456");   // 77
      
          long stop = System.currentTimeMillis();
      
          System.out.println(stop - start);
      }
      
    • 用StringBuilder替代StringBuffer。StringBuilder效率快

      在append()方法中不要使用+号做字符串连接操作

      错误示例:

      StringBuilder sb = new StringBuilder();
      sb.append("111"+"222");	// 还是在做字符串 + 操作!
      
    • 在构造StringBuilder时,要能预估容量就更好

      原因:防止StringBuilder因预先分配的容量不够而做干净扩充!

  3. 与时间有关的性能问题

    • 避免重复构造SimpleDateFormat对象,SimpleDateFormat对象的创建开销很大

    • 避免利用SimpleDateFormat对象,因为SimpleDateFormat对象是不可重用的

    • 建议使用apache工具包提供的:org.apache.commons.lang.time.DateFormatUtils,DateFormatUtils.format(new Date(),“yyyy-MM-dd HH:mm:ss”);

      性能可提高3倍!

      SimpleDateFormat示例:

      public static void main(String[] args) {
          long start = System.currentTimeMillis();
          SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
          String format = simpleDateFormat.format(new Date());
          System.out.println(format);
          long end = System.currentTimeMillis();
          System.out.println(end - start);	// 27
      }
      

      DateFormatUtils示例:

      public static void main(String[] args) {
          long start = System.currentTimeMillis();
          String format = DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss");
          System.out.println(format);
          long end = System.currentTimeMillis();
          System.out.println(end - start);
      }
      
  4. 与for循环有关的性能问题

    • 避免条件判断时调用函数

      错误示例:

      public static void main(String[] args) {
          List<String> lists = new ArrayList<>();
          for (int i = 0; i < 10000; i++) {
              lists.add("aa");
          }
      
          long start = System.currentTimeMillis();
          for (int i = 0; i < lists.size(); i++) {
              System.out.println(lists.get(i));
          }
          long end = System.currentTimeMillis();
          System.out.println(end - start);    // 46
      }
      

      正确示例:

      public static void main(String[] args) {
          List<String> lists = new ArrayList<>();
          for (int i = 0; i < 10000; i++) {
              lists.add("aa");
          }
      
          long start = System.currentTimeMillis();
          for (int i = 0,size = lists.size(); i < size; i++) {
              System.out.println(lists.get(i));
          }
          long end = System.currentTimeMillis();
          System.out.println(end - start);    // 44
      }
      
    • try…catch要放在循环外面

      // 错误的方式:
      for() {
          try {} catch (Exception e) {}
      }
      // 正确的方式:
      try {
          for() {}
      } catch (Exception e) {}
      
    • 避免在循环中反复调用同一个结果集的同一个对象

      // 错误方式for(int i = 0;i < datas.size();i++) {    datas.getData(i).getString("字段名");    datas.getData(i).getString("字段名");    datas.getData(i).getString("字段名");    // datas.getData(i) 重复获取对象}// 正确方式for(int i = 0;i < datas.size();i++) {    类型 变量名 = datas.getData(i);    变量名.getString("字段名");    变量名.getString("字段名");    变量名.getString("字段名");}
      
  5. 与集合类有关的性能问题

    • 能用ArrayList就不要用Vector

    • 能用HashMap就不要用Hashtable

    • 能用HashMap就不要用ConcurrentHashMap

      前三条原因:

      能不加锁就不加锁

    • 用 ConcurrentHashMap 替代 Collections.synchronizedMap(new HashMap());

      原因:控制锁的粒度尽可能小,前者是多个细粒度的局部锁,后者是一把全局锁

    • 在使用容器时能预设容量,尽量预设

      比如:

      new ArrayList(30);new HashMap(30);// 注意,够用就好,不要设置得过大!
      

      原因:防止基于数据实现的ArrayList二次扩充,和HashMap的重hash

  6. 与开关有关的性能问题

    • 不论是框架开关,还是业务开关,到java端后最 好保存为boolean型

      // 错误方式:if ("true".equals(validate)) {    …}// 正确方式:if (validate) {    …}
      

      前者开销是后者的几十倍,字符串越长,开销越大!

  7. 与工具方法有关的性能问题

    • 将小工具函数标识为final

      // 如:public static final boolean isBlank (String str) {    if (null == str || "".equals(str.trim())) {        return true;    }    return false;}
      

      原因:JDK在运行一定次数后JIT(即时编译器)有可能将此final类型的函数内联

  8. 与SQL动态绑定有关的性能问题

    能用PreparedStatement就不要使用Statement

  9. 与反射调用有关的性能问题

    尽可能缓存Method对象,获取Method对象是反射调用最消耗性能的地方

  10. 缓存使用的性能问题

    • 缓存的作用有两个:

      1. 将你要的数据搬到离你更近的地方
      2. 缓存计算

      避免从缓存获取数据后,再对象数据进行排序、过滤等操作。

      正确的做法是,先排序好,过滤完再放进缓存,以后直接拿来用即可。

  11. 并发锁带来的性能问题

    • 最好是不用锁,比如用CAS机制解决并发问题
    • 在读多写少的并发场景,用读写锁,不要有排它锁,如果synchronize
  12. 杂项

    • 避免频繁使用instanceof做类型判断,建议拆成多个对象,用多态调用
    • 能不用正则表达式就不用,正则表达式只是更为灵活,但在特定场景下性能不一定最优
    • 避免重复对象的反复构造,可以复用就复用,尤其是大对象的构造,是非常消耗性能的
    • 两数组对对拷,记得用System.arraycopy(),不要自己写for循环,性能差距非常大
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值