性能文章>提升你Java程序运行性能的10个入门小技巧>

提升你Java程序运行性能的10个入门小技巧转载

2年前
276005

这些技巧可能会多次提高您的应用程序的性能。

程序性能优化是一个复杂的话题。往往需要结合具体场景进行性能分析,找出瓶颈,提出优化建议。但是,假设我们很少注意通常的编码细节并提高多个细节的性能。在这种情况下,优化这些细节的累积性能优势也是相当可观的。今天,我们来聊聊Java代码细节优化的一些小技巧。

复杂的字符串连接操作使用 StringBuilder

在我职业生涯的早期,在做字符串连接操作的时候,我肯定会使用 的写法String a=c+e+d,这个Java语法糖对开发者来说太方便了。但是如果你在这样的循环中使用“+”,你必须小心。

for(int i=0;i<1000;i++) { 
     a=a+i; 
  }

我们都知道字符串是不可变的,所以循环中对字符串的每一次赋值都会在堆内存中创建一个新的字符串对象。在一个循环体中,会重复创建多个无用的对象,不仅会占用内存空间,还会影响GC时间。所以听我说。如果在循环中遇到字符串拼接,请使用StringBuilder 代替“+”。

ThreadPoolExecutor 而不是手动创建线程

许多初学者喜欢在编写代码时创建线程,这是一种危险的做法。

如果这个线程创建需要处理大量的请求,很可能会导致你的程序频繁地创建和销毁线程,频繁地切换线程上下文,浪费CPU资源,甚至耗尽内存。

因此,建议使用ThreadPoolExecutor和配置合适的核心线程数和最大线程数。

为集合预先分配适当的容量

ArrayList我们都知道,HashMap和等集合类ConcurrentHashMap可以自动扩展,但是这种自动扩展涉及到底层数组的复制和迁移。如果扩展频繁,肯定会影响程序的性能。所以如果你能估计出收藏的大概容量,请直接初始分配。

使用枚举而不是常量类

所以很多人特别喜欢在项目中创建一个常量类,像这样。


    public static final String TOKEN_HEADER = "x-request-token";

    public static final Integer CODE_SUCCESS = 0;

    public static final Integer CODE_REQUEST_FAILED = 1;
    
    public static final Integer CODE_REQUEST_RUNNING = 2;
}

伙计们,你能用枚举替换它吗?Enum被强制验证没有错误。同时,使用枚举类的性能更高。并且使用枚举有更大的优势。它可以与策略模式一起使用,以提高程序的可扩展性。例如


    EXCEL(".xlsx"){
        @Override
        public void download(String path) {
        		//do download excel file logic
        }
    }, CSV(".csv") {
        @Override
        public void download(String path) {
          //do download csv file logic
        }
    };

    private String suffix;

    FileType(String suffix) {
        this.suffix = suffix;
    }

    public String getSuffix() {
        return suffix;
    }

    public abstract void download(String path);
}

看,您可以根据需要动态选择下载文件的策略。您可以使用Excel 格式FileType.EXCEL.download()下载文件。

使用 NIO 代替传统 IO

传统的 IO 已经过时了。强烈推荐使用 NIO 替代传统的 io。因为传统IO采用阻塞IO模型,在请求数据后,线程从数据准备到数据可读都是阻塞的。

而且,传统IO如果想往网卡写数据,需要先把数据写到堆内存中,再把数据拷贝到堆外的一块内存,再从用户态拷贝数据到内核​​状态缓冲区。

最后,CPU通知DMA将数据写入网卡,一共经历了三份。NiO不仅使用多路 IO 模型,还可以使用直接内存来减少数据副本的数量以提高性能。

使用移位操作

如果你看过一些 JDK 的源码,比如HashMap,你可以看到代码中有很多移位操作。因为JDK是比较底层的代码,所以对性能的追求也是极致。在我们日常的编码中,我们可以用移位运算代替一些乘除,例如a >> 1for a / 2,a * 16for a << 4。

这个技巧也可以在一定程度上提升性能,但是如果你不擅长,那就不要勉强了,因为当代计算机的性能已经非常强大了,没有必要为了一个代码而牺牲代码可读性。很少的表现。

尝试使用单例模式

如果我们设计一个不需要考虑线程安全的类,请使用单例模式来使用这个类,这样可以节省内存。幸运的是,对于我们使用的Spring 框架, Java bean默认是单例的。

减少锁粒度

假设我们有一个共享文档编辑功能,用户将同时编辑共享文档。为了保证文档的正确性,我们需要使用synchronized来保证线程安全。很多初学者可能会写这个。

    private Object lock = new Object();
    
    public void write(String username, String fileName) {
        synchronized(lock) {
            //do something
        }
    }
}

如果采用上述方法,只有一个线程可以进入同步代码块执行,其他线程只能挂起等待,即使这些线程可能会写不同的文档。我们可以通过降低锁定粒度来提高性能。

    
    public void write(String username, String fileName) {
        synchronized(fileName.intern()) {
            //do something
        }
    }
}

不要随意使用静态变量

如果一个对象被定义为一个静态变量,这个变量的引用就不容易被垃圾回收器回收。

    公共静态A a =新A();
}

静态变量“a”的生命周期与测试类的生命周期相同。只要未卸载测试类型,“a”的引用对象就会驻留在内存中,直到程序终止。

使用基本数据类型

您还可以在应用程序中使用基本数据类型来减少内存消耗并提高程序性能。如果可以使用 int,请不要使用其包装类型 integer,或使用double而不是Double。

基本数据类型的包装类实例存放在堆内存中,每次使用都会在堆内存中创建一个。如果使用基本数据类型,数据存储在栈帧中,栈的访问速度可以比堆快很多。

点赞收藏
分类:标签:
金色梦想

终身学习。

请先登录,感受更多精彩内容
快去登录吧,你将获得
  • 浏览更多精彩评论
  • 和开发者讨论交流,共同进步

为你推荐

JDBC PreparedStatement 字段值为null导致TBase带宽飙升的案例分析

JDBC PreparedStatement 字段值为null导致TBase带宽飙升的案例分析

随机一门技术分享之Netty

随机一门技术分享之Netty

MappedByteBuffer VS FileChannel:从内核层面对比两者的性能差异

MappedByteBuffer VS FileChannel:从内核层面对比两者的性能差异

5
0