어떤 사람들에게는 코드 최적화가 쓸모없어 보일 수도 있지만, 개발 과정에서 좋은 습관을 기르기 위해 최선을 다해야 한다고 생각합니다. 작은 최적화 포인트를 하나씩 쌓으면 확실히 효율성이 크게 향상될 것입니다. . 좋아요, 제가 일반적으로 사용하는 요약을 여러분과 공유하겠습니다.
코드 최적화 목표
1 코드 크기 줄이기
2 성능 향상 전체 시스템 운영 효율성
코드 세부정보 최적화
1 클래스의 최종 수정자를 지정하고 메소드
최종 수정된 클래스는 파생되지 않습니다. Java 핵심 API에는 java.lang.String과 같이 final을 사용하는 예가 많이 있습니다. 클래스에 final 수정자를 지정하면 클래스가 상속되지 않을 수 있고 메서드에 final을 지정하면 됩니다. 메소드가 상속되는 것을 방지합니다. 클래스를 final로 지정하면 해당 클래스의 모든 메서드가 final이 됩니다. Java 컴파일러는 모든 최종 메소드를 인라인할 수 있는 기회를 찾습니다. 인라인은 Java 실행 효율성을 향상시키는 데 중요한 역할을 합니다. 이를 통해 성능을 평균 50% 향상할 수 있습니다.
2 객체 재사용 시도
특히 String 객체를 사용할 경우 StringBuilder/를 사용해야 합니다. 대신 StringBuffer 연결이 발생합니다. JVM(Java Virtual Machine)은 객체를 생성하는 데 시간을 소비할 뿐만 아니라 향후 이러한 객체를 가비지 수집하고 처리하는 데에도 시간을 소비해야 할 수 있습니다. 따라서 너무 많은 객체를 생성하면 프로그램 성능에 큰 영향을 미칩니다.
3 가능하면 로컬 객체를 사용하세요
메서드 호출 시 전달되는 매개변수와 호출 시 생성되는 임시 변수 정적 변수 및 인스턴스 변수와 같은 다른 변수는 모두 스택에 저장되며 속도가 더 느립니다. 또한 메소드가 종료되면 스택에 생성된 변수의 내용은 사라지므로 추가 가비지 수집이 필요하지 않습니다.
4 즉시 스트림을 닫습니다.
Java 프로그래밍 프로세스 중에 데이터베이스 연결을 수행하고 I/ O 스트림 운영 리소스를 해제하기 위해 사용 후 즉시 닫도록 주의하십시오. 이러한 대형 개체를 작동하면 시스템 오버헤드가 많이 발생하므로 조금만 부주의해도 심각한 결과를 초래할 수 있습니다.
5 반복되는 변수 계산을 줄여보세요
개념, 메소드 호출, 메소드 스택 프레임 생성, 메소드 호출 시 장면 보호, 메소드 호출 시 장면 복원 등을 포함하여 소비되는 명령문은 하나만 있습니다. 따라서 예를 들어
for (int i = 0; i < list.size(); i++) {...}
작업을
for (int i = 0, int length = list.size(); i < length; i++) {...}
로 바꾸는 것이 좋습니다. 이런 식으로 list.size()가 크면 소비가 많이 줄어듭니다.
6 지연 로딩 전략을 채택해 보세요. 즉, 필요한 경우에만
을 생성하세요. 예:
String str = "aaa";if (i == 1) { list.add(str); }
는 다음으로 바꾸는 것이 좋습니다.
if (i == 1) {String str = "aaa"; list.add(str); }
7 예외는 주의해서 사용하세요.
예외는 성능에 좋지 않습니다. 예외를 발생시키려면 먼저 새로운 객체를 생성해야 합니다. Throwable 인터페이스의 생성자는 fillInStackTrace()라는 로컬 동기화 메서드를 호출합니다. fillInStackTrace() 메서드는 스택을 확인하고 호출 추적 정보를 수집합니다. 예외가 발생할 때마다 처리 중에 새 객체가 생성되므로 JVM(Java Virtual Machine)은 호출 스택을 조정해야 합니다. 예외는 오류 처리에만 사용해야 하며 프로그램 흐름을 제어하는 데 사용해서는 안 됩니다.
8 루프에서 try...catch...를 사용하지 마십시오.
외부에 배치해야 합니다. 절대적으로 필요합니다. 아무 이유 없이 이런 글을 쓴다면, 리더가 선배이고 강박증이 있는 한, 그런 쓰레기 코드를 썼다고 혼날 가능성이 높습니다
9 추가할 콘텐츠의 길이를 추정할 수 있는 경우 ArrayList, LinkedLlist, StringBuilder 등 배열
에 구현된 기본 컬렉션 및 도구 클래스의 초기 길이를 지정합니다. StringBuffer, HashMap, HashSet 등, StringBuilder를 예로 들면:
(1) StringBuilder() // 기본적으로 공백 16자를 할당합니다
(2) StringBuilder (int size) // 기본 할당은 size 문자 공간
(3) StringBuilder(String str) // 기본 할당은 16자 + str.length() 문자 공간
클래스(여기서는 위의 StringBuilder뿐만 아니라)를 통해 초기화 용량을 설정할 수 있어 성능이 크게 향상될 수 있습니다. 예를 들어 StringBuilder의 길이는 현재 StringBuilder가 보유할 수 있는 문자 수를 나타냅니다. StringBuilder가 최대 용량에 도달하면 용량이 현재 용량의 2배 + 2로 증가하기 때문입니다. StringBuilder가 최대 용량에 도달할 때마다 새 문자 배열을 만든 다음 이전 문자의 내용을 바꿔야 합니다. 배열은 새로운 문자 배열로 복사됩니다. 이는 성능 집약적인 작업입니다. 문자 배열이 길이를 지정하지 않고 대략 5000자를 저장할 것이라고 추정할 수 있다면 2에서 5000까지의 가장 가까운 거듭제곱은 4096이고 각 확장마다 2가 추가될 것이라고 상상해 보십시오. 그러면 다음과 같습니다.
(1) 4096개 기준으로 8194개의 문자배열을 한번에 신청하면 총 12290개의 문자배열을 처음에 지정할 수 있는 경우와 같습니다. 이렇게 하면 공간이 두 배 이상 절약됩니다.
(2) 원래 4096자를 새 문자 배열에 복사합니다.
这样,既浪费内存空间又降低代码运行效率。所以,给底层以数组实现的集合、工具类设置一个合理的初始化容量是错不了的,这会带来立竿见影的效果。但是,注意,像HashMap这种是以数组+链表实现的集合,别把初始大小和你估计的大小设置得一样,因为一个table上只连接一个对象的可能性几乎为0。初始大小建议设置为2的N次幂,如果能估计到有2000个元素,设置成new HashMap(128)、new HashMap(256)都可以。
10 当复制大量数据时,使用 System.arraycopy() 命令
11 乘法和除法使用移位操作
例如:
for (val = 0; val < 100000; val += 5) { a = val * 8; b = val / 2; }
用移位操作可以极大地提高性能,因为在计算机底层,对位的操作是最方便、最快的,因此建议修改为:
for (val = 0; val < 100000; val += 5) { a = val << 3; b = val >> 1; }
移位操作虽然快,但是可能会使代码不太好理解,因此最好加上相应的注释。
12 循环内不要不断创建对象引用
例如:
for (int i = 1; i <= count; i++) {Object obj = new Object(); }
这种做法会导致内存中有count份Object对象引用存在,count很大的话,就耗费内存了,建议为改为:Object obj = null;for (int i = 0; i <= count; i++) { obj = new Object(); }
这样的话,内存中只有一份Object对象引用,每次new Object()的时候,Object对象引用指向不同的Object罢了,但是内存中只有一份,这样就大大节省了内存空间了。
13基于效率和类型检查的考虑,应该尽可能使用array,无法确定数组大小时才使用ArrayList
14尽量使用HashMap、ArrayList、StringBuilder,除非线程安全需要,否则不推荐使用Hashtable、Vector、StringBuffer,后三者由于使用同步机制而导致了性能开销
15 不要将数组声明为 public static final
因为这毫无意义,这样只是定义了引用为 static final ,数组的内容还是可以随意改变的,将数组声明为 public 更是一个安全漏洞,这意味着这个数组可以被外部类所改变
16 尽量在合适的场合使用单例
使用单例可以减轻加载的负担、缩短加载的时间、提高加载的效率,但并不是所有地方都适用于单例,简单来说,单例主要适用于以下三个方面:
(1)控制资源的使用,通过线程同步来控制资源的并发访问
(2)控制实例的产生,以达到节约资源的目的
(3)控制数据的共享,在不建立直接关联的条件下,让多个不相关的进程或线程之间实现通信
17 尽量避免随意使用静态变量
要知道,当某个对象被定义为 static 的变量所引用,那么 gc 通常是不会回收这个对象所占有的堆内存的,如:
public class A{private static B b = new B(); }
以上就是Java开发代码性能优化总结的内容,更多相关内容请关注PHP中文网(www.php.cn)!