동시 처리


1. [필수] 싱글톤 객체를 얻으려면 스레드 안전성이 보장되어야 하며 메서드도 스레드 안전성을 보장해야 합니다.

설명: 리소스 기반 클래스, 도구 클래스 및 싱글톤 팩토리 클래스를 모두 언급해야 합니다.

2. [필수] 오류 발생 시 역추적을 용이하게 하기 위해 스레드 또는 스레드 풀 생성 시 의미 있는 스레드 이름을 지정하십시오.

긍정적인 예:

public class TimerTaskThread extends Thread {
public TimerTaskThread(){
super.setName("TimerTaskThread"); ...
}

3 [필수] 스레드 리소스는 스레드 풀을 통해 제공되어야 하며 명시적으로 생성할 수 없습니다. 응용 프로그램에서.

설명: 스레드 풀을 사용하면 스레드 생성 및 소멸에 소요되는 시간과 시스템 리소스 비용을 줄이고 리소스 부족 문제를 해결할 수 있다는 장점이 있습니다. 질문입니다. 스레드 풀을 사용하지 않으면 시스템에서 유사한 스레드를 많이 생성하여 메모리 소비 또는 "과도한 전환" 문제가 발생할 수 있습니다.


4 [필수] 스레드 풀은 Executor를 사용하여 생성하는 것을 허용하지 않지만 ThreadPoolExecutor를 통해 생성하므로 #🎜🎜 # 처리 방법을 통해 글쓰기 학생들은 스레드 풀의 운영 규칙을 보다 명확하게 파악하고 리소스 고갈 위험을 피할 수 있습니다.

설명: Executor가 반환한 스레드 풀 개체의 단점은 다음과 같습니다.

1)

FixThreadPool #🎜🎜 #And SingleThreadPool :허용되는 요청 대기열 길이는 Integer.MAX_VALUE이며, 이로 인해 많은 수의 요청이 누적되어 OOM이 발생할 수 있습니다.

2)

CachedThreadPool

ScheduledThreadPool: 생성할 수 있는 스레드 수는 Integer.MAX_VALUE입니다. , 이는 많은 수의 스레드를 생성하여 OOM으로 이어질 수 있습니다.


5. [필수] SimpleDateFormat은 스레드에 안전하지 않은 클래스이므로 일반적으로 정적 변수로 정의하지 마세요. 🎜#static, 잠그거나 DateUtils 유틸리티 클래스를 사용해야 합니다.

긍정적인 예:

스레드 안전에 주의하고 DateUtils를 사용하세요. 다음 처리도 권장됩니다:

private static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>() {
@ Override
protected DateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd");
}
};
참고:

JDK 8 애플리케이션인 경우 Date 대신 Instant, Calendar 대신 LocalDateTime, #🎜🎜을 사용할 수 있습니다. Simpledateformatter 대신 #DateTimeFormatter, 공식 설명 제공: 단순하고 아름답고 강함

불변 스레드 - 안전함.

6 [필수] 동시성이 높을 때 동기 호출은 잠금 성능 손실을 고려해야 합니다. 잠금 없는 데이터 구조를 사용할 수 있다면 잠금을 사용하지 마세요.

블록을 잠글 수 있다면 전체 메소드 본문을 잠그지 마세요. 객체 잠금을 사용할 수 있다면 클래스 잠금을 사용하지 마세요.

7. [필수] 여러 리소스, 데이터베이스 테이블 및 개체를 동시에 잠글 때 일관된 잠금 순서를 유지해야 합니다. 그렇지 않으면 교착 상태가 발생할 수 있습니다.

설명: 스레드 1은 업데이트 작업을 수행하기 전에 모든 테이블 A, B, C를 순서대로 잠가야 합니다. 그러면 스레드 2의 잠금 순서도 A, B, C여야 합니다. 그렇지 않으면 교착 상태가 됩니다. 발생할 수 있습니다.


8. 동일한 레코드를 동시에 수정하는 경우 업데이트 손실을 방지하려면 애플리케이션 계층에서 잠그거나 캐시에 잠그거나

데이터베이스 계층에서 낙관적 잠금을 사용하고 버전을 사용하세요. 업데이트 기준으로.

참고:

액세스당 ​​충돌 확률이 20% 미만이면 낙관적 잠금을 사용하는 것이 좋으며, 그렇지 않으면 비관적 잠금을 사용하는 것이 좋습니다. 낙관적 잠금의 재시도 횟수는 3회 이상이어야 합니다.

9. 멀티 스레드가 예약된 작업을 병렬로 처리하는 경우 Timer가 여러 TimeTask를 실행할 때 그 중 하나가 발생한 예외를 포착하지 않는 한

다른 작업은 자동으로 종료되지 않습니다. ScheduledExecutorService 질문을 사용하는 경우입니다.

10. 비동기 작업을 동기 작업으로 수행하려면 CountDownLatch를 사용하세요. 각 스레드는 종료하기 전에 countDown


메서드를 호출하여 countDown 메서드가 작동할 수 있도록 해야 합니다. 메인 스레드가 실행되지 않는 것을 방지하기 위해 실행됩니다

countDown 메소드의 경우 타임아웃이 될 때까지 결과가 반환되지 않습니다.

참고:

자식 스레드에서 발생한 예외 스택은 기본 스레드의 try-catch로 접근할 수 없습니다.

11. [권장] 여러 스레드에서 임의 인스턴스를 사용하지 마세요. 이 인스턴스를 공유하는 것은 스레드로부터 안전하지만 동일한

시드에 대한 경쟁으로 인해 성능 저하가 발생합니다.

참고: Random 인스턴스에는 java .util .Random 인스턴스 또는 Math .random() 인스턴스가 포함됩니다.

긍정적인 예: JDK 7 이후에는 API ThreadLocalRandom을 직접 사용할 수 있습니다. JDK 7 이전에는

스레드당 하나의 인스턴스를 얻을 수 있습니다.

12. [권장사항] 지연된 초기화의 숨겨진 위험을 최적화하려면 이중 확인 잠금(동시 시나리오에서)을 사용하십시오(" 이중 확인 잠금이 손상됨" 선언 참조). 문제에 대한 더 간단한 해결책을 권장합니다.


(JDK 5 이상에 적용 가능)은 대상 속성을 휘발성으로 선언하는 것입니다.

카운터 예시:

class Foo {
private Helper helper = null;
public Helper getHelper() {
if (helper == null) synchronized(this) {
if (helper == null)
helper = new Helper();
}
return helper;
}
// other functions and members...
}

13. [참고] 휘발성은 멀티 스레드에서 보이지 않는 메모리 문제를 해결합니다. 한 번의 쓰기와 여러 번의 읽기의 경우 변수 동기화 문제는 해결되지만, 쓰기가 여러 번 발생하면 스레드 안전성 문제는 해결되지 않습니다. count ++ 작업인 경우 다음 클래스를 사용하여 구현합니다. AtomicInteger count = new AtomicInteger() count . JDK 8인 경우 을 권장합니다. LongAdder 개체를 사용하면 AtomicLong보다 성능이 더 좋습니다(낙관적 잠금 재시도 횟수가 줄어듭니다).


14. [참고] HashMap의 크기 조정 용량이 부족할 경우 높은 동시성으로 인해 데드 링크가 발생하여 CPU가 작동하지 않을 수 있습니다. 🎜🎜#

개발 과정에서 이러한 위험이 발생하지 않도록 주의하세요.


15. [참고] ThreadLocal은 공유 객체의 업데이트 문제를 해결할 수 없습니다. ThreadLocal 객체는 static

으로 장식하는 것이 좋습니다. 이 변수는 스레드 내의 모든 작업에 공통되므로 정적 변수로 설정됩니다. 이러한 모든 인스턴스는 이 정적 변수를 공유합니다. 즉, 클래스가 처음으로 사용될 때 로드됩니다. 시간만 할당되며 저장 공간의 일부인 모든 개체(이 스레드 내에 정의된 만 해당)가 이 변수를 조작할 수 있습니다.