이 기사의 예에는 Java 성능 최적화 기술이 요약되어 있습니다. 참고할 수 있도록 모든 사람과 공유하세요. 구체적인 분석은 다음과 같습니다.
여기서는 대부분의 Java 애플리케이션에 적합한 몇 가지 책과 네트워크 리소스를 참조합니다.
JAVA 프로그램에서 성능 문제의 원인은 대부분 JAVA 언어에 있는 것이 아니라 프로그램 자체에 있습니다. 좋은 코딩 습관을 기르는 것은 매우 중요하며 프로그램 성능을 크게 향상시킬 수 있습니다.
1. 최종 수식어를 사용해 보세요.
final 수정자가 있는 클래스는 파생되지 않습니다. JAVA Core API에는 java.lang.String 등 final을 적용한 예가 많이 있습니다. String 클래스에 final을 지정하면 사용자가 length() 메서드를 재정의할 수 없습니다. 또한 클래스가 final이면 해당 클래스의 모든 메서드도 final입니다. Java 컴파일러는 모든 최종 메소드를 인라인할 수 있는 기회를 찾습니다(이는 특정 컴파일러 구현에 따라 다름). 이를 통해 성능을 평균 50% 향상할 수 있습니다.
2. 객체를 재사용해 보세요.
특히 String 개체를 사용하는 경우 문자열 연결이 발생할 때 대신 StringBuffer를 사용해야 합니다. 시스템은 개체를 생성하는 데 시간을 소비해야 할 뿐만 아니라 향후 이러한 개체를 가비지 수집하고 처리하는 데 시간도 소비해야 할 수도 있습니다. 따라서 너무 많은 개체를 생성하면 프로그램 성능에 큰 영향을 미칩니다.
3. 지역변수를 사용해 보세요.
메소드 호출 시 전달된 파라미터와 호출 시 생성된 임시 변수는 스택(Stack)에 저장되므로 속도가 더 빠릅니다. 정적 변수, 인스턴스 변수 등과 같은 다른 변수는 힙에 생성되며 속도가 느립니다.
4. 변수를 반복적으로 초기화하지 마십시오.
기본적으로 클래스의 생성자를 호출하면 Java는 변수를 특정 값으로 초기화하고 모든 객체는 null로 설정되고 정수 변수는 0으로 설정되고 float 및 double 변수는 0.0으로 설정되고 논리값은 으로 설정됩니다. 거짓. 클래스가 다른 클래스에서 파생될 때 특히 주의해야 합니다. 왜냐하면 new 키워드를 사용하여 객체를 생성하면 생성자 체인의 모든 생성자가 자동으로 호출되기 때문입니다.
여기서 주의할 점은 멤버 변수의 초기값을 설정했는데 다른 메소드를 호출해야 할 경우에는 값을 할당하는 메소드를 직접 호출하면 null이 발생할 수 있으므로 initXXX()와 같은 메소드에 넣는 것이 가장 좋습니다. 클래스가 초기화되지 않았기 때문에 포인터 예외가 발생했습니다. public int state = this.getState();
5. Java+Oracle 응용 시스템 개발 시 Java에 내장된 SQL 언어는 최대한 대문자로 표기하여 Oracle 파서의 파싱 부담을 줄여야 한다.
6. Java 프로그래밍 프로세스 중에 데이터베이스 연결 및 I/O 스트림 작업을 수행한 후 리소스를 해제하기 위해 제때에 닫습니다. 이러한 대형 개체에 대한 작업으로 인해 시스템 오버헤드가 많이 발생하기 때문입니다.
7. 객체를 과도하게 생성하면 많은 양의 시스템 메모리가 소모되며 심각한 경우 메모리 누수로 이어질 수 있으므로 만료된 객체를 적시에 재활용하는 것이 매우 중요합니다.
JVM의 GC는 그리 스마트하지 않기 때문에 객체 사용 후 수동으로 null로 설정하는 것이 좋습니다.
8. 동기화 메커니즘을 사용할 때 코드 블록 동기화 대신 메소드 동기화를 사용해 보십시오.
9. 변수의 이중 계산을 최소화합니다.
예를 들어
for(int i=0;i<list.size();i++)
로 수정되어야 한다
for(int i=0,len=list.size();i<len;i++)
10. 필요할 때만 창조하는 전략을 채택하십시오.
예를 들어:
문자열 str="abc";if(i==1){ list.add(str);}
다음과 같이 수정해야 합니다.
if(i==1){String str="abc"; list.add(str);}
11. 예외는 성능에 해롭기 때문에 주의해서 사용하십시오.
먼저 예외를 발생시키면 새 객체가 생성됩니다. Throwable 인터페이스의 생성자는 fillInStackTrace()라는 로컬 메서드를 호출합니다. fillInStackTrace() 메서드는 스택을 확인하고 호출 추적 정보를 수집합니다. 예외가 발생할 때마다 처리 중에 새 개체가 생성되므로 VM은 호출 스택을 조정해야 합니다.
예외는 오류 처리에만 사용해야 하며 프로그램 흐름을 제어하는 데 사용해서는 안 됩니다.
12. 루프에서 Try/Catch 문을 사용하지 마십시오. Try/Catch는 루프의 가장 바깥쪽 수준에 배치되어야 합니다.
Error는 시스템 오류 또는 가상 머신 오류를 가져오는 클래스입니다. 모든 오류 예외를 얻을 수 있는 것은 아닙니다. 가상 머신이 오류 예외를 보고하는 경우 이를 얻으려면 오류를 사용해야 합니다.
13. 생성자를 통해 StringBuffer의 초기 용량을 설정하면 성능이 크게 향상될 수 있습니다.
StringBuffer의 기본 용량은 16입니다. StringBuffer의 용량이 최대 용량에 도달하면 현재 용량의 2배 + 2인 2*n+2로 용량이 늘어납니다. StringBuffer가 최대 용량에 도달할 때마다 새로운 개체 배열을 만든 다음 이전 개체 배열을 복사해야 하므로 많은 시간이 낭비됩니다. 따라서 StringBuffer에 대한 합리적인 초기 용량 값 설정이 필요합니다!
14. java.util.Vector를 합리적으로 사용하세요.
Vector는 StringBuffer와 유사하며 용량이 확장될 때마다 기존의 모든 요소를 새로운 저장 공간에 할당해야 합니다. Vector의 기본 저장 용량은 10개 요소이며, 용량은 두 배로 늘어납니다.
vector.add(index,obj) 이 메소드는 obj 요소를 인덱스 위치에 삽입할 수 있지만 인덱스와 후속 요소는 한 위치 아래로 이동해야 합니다(인덱스를 1씩 증가). 꼭 필요한 경우가 아니면 성능이 좋지 않습니다.
이 벡터의 지정된 위치에 있는 요소를 제거하는 제거(int index) 메서드에도 동일한 규칙이 적용됩니다. 모든 후속 요소를 왼쪽으로 이동합니다(인덱스를 1씩 감소). 이 벡터에서 제거된 요소를 반환합니다. 따라서 벡터의 마지막 요소를 삭제하는 것이 첫 번째 요소를 삭제하는 것보다 비용이 훨씬 저렴합니다. 모든 요소를 제거하려면 RemoveAllElements() 메서드를 사용하는 것이 가장 좋습니다.
벡터에서 요소를 삭제하려면 vector.remove(obj)를 사용할 수 있습니다. int index = indexOf(obj);와 같이 요소 위치를 직접 검색한 다음 삭제할 필요가 없습니다. 색인);
15. 대용량 데이터를 복사할 때는 System.arraycopy()를 사용하세요.
16. 코드 가독성을 높이기 위한 코드 리팩토링.
17. new 키워드를 사용하지 않고 개체의 인스턴스를 만듭니다.
new 키워드를 사용하여 클래스의 인스턴스를 생성하면 생성자 체인의 모든 생성자가 자동으로 호출됩니다. 그러나 객체가 Cloneable 인터페이스를 구현하는 경우 해당 객체의 clone() 메서드를 호출할 수 있습니다. clone() 메서드는 클래스 생성자를 호출하지 않습니다.
다음은 Factory 패턴의 일반적인 구현입니다.
public static Credit getNewCredit(){ return new Credit();} 개선된 코드는 clone() 메소드를 사용합니다. private static Credit BaseCredit = new Credit() public static Credit getNewCredit(){ return (Credit)BaseCredit.clone() ;}
18. 변위를 곱셈과 나눗셈에 사용할 수 있다면 변위를 최대한 활용해야 하지만 변위 연산이 직관적이지 않고 이해하기 어렵기 때문에 주석을 추가하는 것이 가장 좋습니다.
19. 배열을 public static final로 선언하지 마십시오.
20.HaspMap 순회.
Map<String, String[]> paraMap = new HashMap<String, String[]>();for( Entry<String, String[]> 항목 : paraMap.entrySet() ){ String appFieldDefId = Entry.getKey(); 문자열[] 값 =entry.getValue();}
해시 값을 사용하여 비교를 위한 해당 항목을 검색하여 결과를 얻습니다. 항목 값을 얻은 후 키와 값을 직접 얻습니다.
21. 배열(array)과 ArrayList의 사용.
배열 배열은 가장 효율적이지만 용량이 고정되어 동적으로 변경할 수 없습니다. ArrayList의 용량은 동적으로 늘릴 수 있지만 효율성이 희생됩니다.
22. 단일 스레드는 HashMap과 ArrayList를 사용해야 합니다. 필요한 경우가 아니면 HashTable과 Vector를 사용하는 것은 권장되지 않으며 성능이 저하됩니다.
23. StringBuffer와 StringBuilder의 차이점은 다음과 같습니다. java.lang.StringBuffer는 스레드로부터 안전한 변수 문자 시퀀스입니다. String과 유사하지만 수정할 수 없는 문자열 버퍼입니다. StringBuilder StringBuilder 클래스는 동일한 작업을 모두 지원하지만 동기화를 수행하지 않기 때문에 더 빠르기 때문에 일반적으로 이 클래스보다 우선적으로 사용되어야 합니다. 더 나은 성능을 얻으려면 StringBuffer 또는 StringBuilder를 구성할 때 용량을 지정해야 합니다. 물론 16자를 넘지 않으면 필요하지 않습니다.
동일한 상황에서 StringBuilder를 사용하면 StringBuffer를 사용할 때보다 10~15%의 성능 향상만 얻을 수 있지만 멀티스레딩이 불안정해질 위험이 있습니다. 종합적으로 고려한 후 StringBuffer를 사용하는 것이 좋습니다.
24. 객체 대신 기본 데이터 유형을 사용해 보십시오.
25. 삼각함수 문제를 해결하기 위해 표를 찾는 등 복잡한 함수 계산 대신 간단한 수치 계산을 사용하십시오 .
26. 구체적인 비유를 사용하는 것이 인터페이스를 사용하는 것보다 더 효율적이지만 구조적 유연성이 떨어지지만 최신 IDE는 이 문제를 해결할 수 있습니다.
27. 정적 메소드 사용을 고려해보세요
객체 외부에 액세스할 필요가 없다면 메서드를 정적으로 만드세요. 가상 기능 안내 테이블이 필요하지 않기 때문에 호출 속도가 더 빨라집니다. 이 동료도 좋은 습관입니다. 왜냐하면 그녀는 메소드의 성격을 구별하는 방법을 알려주기 때문입니다. 이 메소드를 호출해도 객체의 상태는 변경되지 않습니다.
28. 내장된 GET 및 SET 메소드의 사용은 가능한 한 피해야 합니다.
Android 프로그래밍에서 가상 메소드를 호출하면 비용이 많이 발생하며 이는 인스턴스 속성 쿼리보다 비용이 더 많이 듭니다. 호출을 아웃소싱할 때는 get 및 set 메서드만 사용해야 하지만, 내부적으로 호출할 때는 직접 호출해야 합니다.
29. 열거형과 부동소수점 숫자의 사용을 피하세요.
30. 2차원 배열은 1차원 배열보다 계산의 약 10배에 달하는 더 많은 메모리 공간을 차지합니다.
31. SQLite 데이터베이스는 전체 테이블의 모든 데이터를 매우 빠르게 읽습니다. 그러나 조건부 쿼리는 30-50MS가 소요됩니다. 이 작업을 수행할 때 모든 사람은 가능한 한 적게 사용하도록 주의해야 합니다. 특히 중첩 검색은 더욱 그렇습니다.
이 글이 모든 사람의 Java 프로그래밍에 도움이 되기를 바랍니다.