자바 에서 자주 사용 하 는 원자 류 를 상세 하 게 정리 하 다.
자바 에 서 는 원자 류 를 제공 하고 원자 류 는 변 수 를 포장 하 며 변 수 를 원자 적 으로 조작 하 는 일련의 방법 을 제공 했다.우 리 는 다 중 스 레 드 환경 에서 이런 원자 류 를 조작 할 때 자 물 쇠 를 추가 하지 않 아 도 되 고 병발 프로 그래 밍 의 개발 을 크게 간소화 했다.
2.원자 류 의 밑바닥 실현
현재 자바 에서 제공 하 는 원자 류 의 대부분 밑바닥 은 CAS 자물쇠(CompareAndSet 자선 자물쇠)를 사용 하고 있다.예 를 들 어 AtomicInteger,AtomicLong 등 이다.세그먼트 잠 금+CAS 잠 금 을 사용 한 원자 류,예 를 들 어 LongAdder 등 도 있다.
3.자주 사용 하 는 원자 류
3.1 AtomicInteger 와 AtomicLong
AtomicInteger 와 AtomicLong 의 밑바닥 실현 은 용법 과 기본적으로 같다.다른 점 은 AtomicInteger 가 Integer 형 변 수 를 포 장 했 고 AtomicLong 은 Long 형 변 수 를 포 장 했 기 때문이다.
AtomicInteger 와 AtomicLong 의 밑바닥 실현 은 모두 CAS 자 물 쇠 를 사용 했다.
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
/**
* @author IT00ZYQ
* @date 2021/5/24 15:33
**/
public class T13_AtomicInteger {
private static AtomicInteger atomicInteger = new AtomicInteger();
private static AtomicLong atomicLong = new AtomicLong();
private static Integer integer = 0;
private static Long lon = 0L;
public static void main(String[] args) {
// 10 , atomicInteger、atomicLong、integer、lon 1000 1
// , = 10 * 1000 = 10000
Thread[] threads = new Thread[10];
for (int i = 0; i < 10; i++) {
threads[i] = new Thread(() -> {
for (int j = 1; j <= 1000; j++) {
atomicInteger.incrementAndGet();
atomicLong.incrementAndGet();
integer ++;
lon ++;
}
});
}
//
for (Thread thread : threads) {
thread.start();
}
// 10
try {
for (Thread thread : threads) {
thread.join();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("AtomicInteger :" + atomicInteger);
System.out.println("AtomicLong :" + atomicLong);
System.out.println("Integer :" + integer);
System.out.println("Long :" + lon);
}
}
실행 결과:AtomicInteger 결과:10000
AtomicLong 결과:10000
Integer 결과:4880
Long 결과:4350
Process finished with exit code 0
여러 차례 실 행 된 원자 류 AtomicInteger 와 AtomicLong 은 매번 정확 한 결 과 를 얻 을 수 있 지만 비 원자 류 Integer 와 Long 은 일반적으로 10000 에 이 르 지 못 하고 매번 결과 도 다 를 수 있 습 니 다.
3.2 LongAdder
LongAdder 의 밑바닥 은 분 단 자 물 쇠 를 사 용 했 고 각 단락 은 CAS 자 물 쇠 를 사 용 했 기 때문에 LongAdder 의 밑바닥 은 분 단 자물쇠+CAS 자 물 쇠 를 실현 했다.
위의 프로그램 에 LongAdder 변 수 를 추가 하여 테스트 합 니 다.
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAdder;
/**
* @author IT00ZYQ
* @date 2021/5/24 15:33
**/
public class T13_AtomicInteger {
private static AtomicInteger atomicInteger = new AtomicInteger();
private static AtomicLong atomicLong = new AtomicLong();
private static LongAdder longAdder = new LongAdder();
private static Integer integer = 0;
private static Long lon = 0L;
public static void main(String[] args) {
// 10 , atomicInteger、atomicLong、integer、lon 1000 1
// , = 10 * 1000 = 10000
Thread[] threads = new Thread[10];
for (int i = 0; i < 10; i++) {
threads[i] = new Thread(() -> {
for (int j = 1; j <= 1000; j++) {
atomicInteger.incrementAndGet();
atomicLong.incrementAndGet();
integer ++;
lon ++;
longAdder.increment();
}
});
}
//
for (Thread thread : threads) {
thread.start();
}
// 10
try {
for (Thread thread : threads) {
thread.join();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("AtomicInteger :" + atomicInteger);
System.out.println("AtomicLong :" + atomicLong);
System.out.println("Integer :" + integer);
System.out.println("Long :" + lon);
System.out.println("LongAdder :" + longAdder);
}
}
실행 결과:AtomicInteger 결과:10000
AtomicLong 결과:10000
Integer 결과:6871
Long 결과:6518
LongAdder 결과:10000
Process finished with exit code 0
LongAdder 류 도 결 과 를 정확하게 출력 할 수 있다.
4.원자 류 의 성능 테스트
4.1 테스트 프로그램
package juc;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.atomic.LongAdder;
/**
* @author IT00ZYQ
* @date 2021/5/24 15:51
**/
public class T14_AtomicClassPerformance {
private static AtomicLong atomicLong = new AtomicLong();
private static LongAdder longAdder = new LongAdder();
/**
*
*/
private static final int THREAD_COUNT = 100;
/**
*
*/
private static final int OPERATION_COUNT = 10000;
public static void main(String[] args) {
Thread[] threads = new Thread[THREAD_COUNT];
// AtomicLong
for (int i = 0; i < THREAD_COUNT; i++) {
threads[i] = new Thread(() -> {
for (int j = 0; j < OPERATION_COUNT; j++) {
atomicLong.incrementAndGet();
}
});
}
long start1 = System.currentTimeMillis();
//
for (Thread thread : threads) {
thread.start();
}
//
try {
for (Thread thread : threads) {
thread.join();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
long end1 = System.currentTimeMillis();
// LongAdder
for (int i = 0; i < THREAD_COUNT; i++) {
threads[i] = new Thread(() -> {
for (int j = 0; j < OPERATION_COUNT; j++) {
longAdder.increment();
}
});
}
long start2 = System.currentTimeMillis();
//
for (Thread thread : threads) {
thread.start();
}
//
try {
for (Thread thread : threads) {
thread.join();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
long end2 = System.currentTimeMillis();
System.out.println("AtomicLong : " + (end1 - start1) + "ms, :" + atomicLong);
System.out.println("LongAdder : " + (end2 - start2) + "ms, :" + longAdder);
}
}
4.2 테스트 결과4.567914 시의 운행 결과
AtomicLong 실행 시간:40ms,실행 결과:100000
LongAdder 운행 시간:57ms,운행 결과:100000
Process finished with exit code 0
4.567914 시의 운행 결과
AtomicLong 실행 시간:108 ms,실행 결과:1000000
LongAdder 운행 시간:85ms,운행 결과:1000000
Process finished with exit code 0
4.567914 시의 운행 결과
AtomicLong 운행 시간:6909 ms,운행 결과:100000000
LongAdder 운행 시간:468 ms,운행 결과:100000000
Process finished with exit code 0
4.567914 시의 운행 결과
AtomicLong 운행 시간:788 ms,운행 결과:10000000
LongAdder 운행 시간:162 ms,운행 결과 10000000
Process finished with exit code 0
4.3 결과 분석
4
THREAD_COUNT = 100, OPERATION_COUNT = 1000
충분 한 시간 동안 AtomicInteger 의 성능 은 LongAdder 보다 약간 높 을 것 이다.4.567914.증가 함 에 따라 LongAdder 의 성능 이 더욱 높 고 4.567914.충분 할 때 LongAdder 의 성능 은 AtomicInteger 보다 훨씬 높다.4.4 밑바닥 실현 분석
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JPA + QueryDSL 계층형 댓글, 대댓글 구현(2)이번엔 전편에 이어서 계층형 댓글, 대댓글을 다시 리팩토링해볼 예정이다. 이전 게시글에서는 계층형 댓글, 대댓글을 구현은 되었지만 N+1 문제가 있었다. 이번에는 그 N+1 문제를 해결해 볼 것이다. 위의 로직은 이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.