일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- git
- mysql
- Linux
- rsync
- 명령어
- 자바
- API
- JPA
- PostgreSQL
- MariaDB
- mssql
- 트랜잭션
- group by
- DBMS
- oracle
- 차이점
- Javascript
- MongoDB
- IntelliJ
- 티스토리챌린지
- spring
- Python
- 리눅스
- SQL
- 오블완
- docker
- analytics4
- top
- network
- java
- Today
- Total
hanker
JAVA - 멀티 쓰레드 연산처리 (AtomicInteger) 본문
https://hanke-r.tistory.com/229
이전 글에 이어 멀티쓰레드 처리 시 연산처리를 하는 방법을 알아보자.
연산 처리할 경우에 ( java.util.concurrent.atomic ) 패키지중 AtomicInteger 클래스를 사용하려고 한다.
AtomicInteger 클래스는 Java 5 버전 이상부터 사용 가능하다.
또한 일반 int와 달리 여러 스레드에서 동시에 접근해도 값이 유지되고, 동기화(synchronization) 없이 스레드의 동시성을 보장한다.
코드를 보자(코드는 이전글에 작성했던 코드를 응용해서 작성)
public static void main(String[] args) throws Exception {
List<Map<String, Object>> list = new ArrayList<>();
for (int i = 0; i < 200; i++) {
Map<String, Object> map = new HashMap<>();
map.put("number", i);
list.add(map);
}
ExecutorService executor = Executors.newFixedThreadPool(8); // 8개의 쓰레드 생성
AtomicInteger atomicInteger = new AtomicInteger(0);
for(int i = 0 ; i < list.size() ; i++) {
final int number = Integer.parseInt(list.get(i).get("number").toString());
executor.submit(() -> {
atomicInteger.set(atomicInteger.get() + number);
System.out.println(Thread.currentThread().getName() + " : " + number);
});
}
executor.shutdown(); // 모든 작업이 끝난 후 쓰레드 종료
try {
// 모든 작업이 완료될 때까지 대기 (최대 50초)
if (executor.awaitTermination(50, TimeUnit.SECONDS)) {
System.out.println(atomicInteger.get());
} else {
executor.shutdownNow();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
추가된 코드를 한줄 한줄 보자
멀티쓰레드 처리하는곳에 final int sum = 0; sum += number; 이렇게 하면 안되나?? 할 수 있겠지만, 안된다. 오류난다
람다 표현식 안에서는 변수가 final 이어야 하는데, final 키워드로 명시된 변수는 선언 후 값 변경이 될 수 없다.
(Variable used in lambda expression should be final or effectively final 오류 발생)
AtomicInteger atomicInteger = new AtomicInteger(0);
- AtomicInteger 초기값 0으로 선언해준다
atomicInteger.set(atomicInteger.get() + number);
- atomicInteger에 저장된 값을 불러와서 number 값이랑 더한 후 다시 atomicInteger에 저장 (+=와 같은 기능)
try {
// 모든 작업이 완료될 때까지 대기 (최대 50초)
if (executor.awaitTermination(50, TimeUnit.SECONDS)) {
System.out.println(atomicInteger.get());
} else {
executor.shutdownNow();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
- executor.awaitTermination 을 사용한 이유가 작업이 완료되기전에 출력되기 때문에, 작업이 완료된 이후에 출력되게 변경
만약 위 코드 없이 출력하였다면 콘솔창에 중간에 더해진 값이 나올것이다. (값도 안맞음)
위 코드를 실행시켜 보면
쓰레드가 전체 다 종료 된 이후 결과 값이 나온걸 확인할 수 있다.
AtomicInteger 클래스의 주요 메서드 정리
1. get() : 현재값 반환
AtomicInteger atomicInteger = new AtomicInteger(621);
atomicInteger.get();
// 출력 결과 : 621
2. set(int value) : 새로운 값으로 설정
AtomicInteger atomicInteger = new AtomicInteger(0);
atomicInteger.set(621);
// atomicInteger = 621
3. lazySet(int value) : 새로운 값으로 설정하되, 즉시 반영되지 않고 나중에 반영 (지연설정)
AtomicInteger atomicInteger = new AtomicInteger(0);
atomicInteger.lazySet(621);
4. getAndSet(int value) : 현재값 반환 후 새로운 값으로 설정
AtomicInteger atomicInteger = new AtomicInteger(621);
int number = atomicInteger.getAndSet(10); // number = 621 , atomicInteger = 10
5. compareAndSet(int expect, int update) : expect 값이 atomicInteger 에 설정된 값과 같으면 update 값으로 변경
AtomicInteger atomicInteger = new AtomicInteger(621);
boolean result = atomicInteger.compareAndSet(621 , 25);
// result = true, 값이 25로 변경됨
6. getAndIncrement() : 현재 값 반환 후 1증가
AtomicInteger atomicInteger = new AtomicInteger(621);
int number = atomicInteger.getAndIncrement()
// number = 621, atomicInteger = 622
7. incrementAndGet() : 값을 1 증가 시킨 후 반환
AtomicInteger atomicInteger = new AtomicInteger(621);
int number = atomicInteger.incrementAndGet();
// number = 622
8. getAndDecrement() : 현재 값 반환 후 1 감소
AtomicInteger atomicInteger = new AtomicInteger(621);
int number = atomicInteger.getAndDecrement();
// number = 621, atomicInteger = 620
9. decrementAndGet() : 값을 1 감소 시킨 후 반환
AtomicInteger atomicInteger = new AtomicInteger(621);
int number = atomicInteger.decrementAndGet();
// number = 620
10. getAndAdd(int number) : 현재 값을 반환하고 number 만큼 더함
AtomicInteger atomicInteger = new AtomicInteger(621);
int number = atomicInteger.addAndGet(9);
// number = 630
끝.
'JAVA' 카테고리의 다른 글
JAVA - 값 비교 (문자열 / 숫자 등등) (0) | 2024.11.08 |
---|---|
JAVA - HttpUrlConnection, HttpsUrlConnection (Content-Type 설정) (2) (0) | 2024.10.20 |
JAVA - 멀티쓰레드(Multi Thread) 반복문 병렬처리 방법 (1) | 2024.10.12 |
Java - (Window/Linux) 디렉터리 목록 가져오기 (1) | 2024.09.20 |
JAVA - Lambda (java 8) (0) | 2024.09.15 |