(ThreadLocalMap)
를 가지고 있다.반환
설정
제거
초기화
public class MyRunnable implements Runnable {
private static int var = 0;
private int order;
public MyRunnable(int order) {
this.order = order;
}
@Override
public void run() {
for (int i = 0; i < 5; i++) {
var += 1;
String str = i == 0 ? " --init" : "";
System.out.println("Thread - " + order + " / " + " [" + i + "] " + " - " + var + str);
}
}
}
public class ThreadLocalBefore {
public static void main(String[] args) {
for (int i = 0; i < 2; i++) {
Thread thread = new Thread(new MyRunnable(i));
thread.start();
}
}
}
💡 동시성 문제
- 다수의 Thread가 하나의 공유 데이터
(동일한 자원)
를 조작할 때 발생하는 문제로 데이터 정합성 문제가 발생한다.
public class ThreadLocalMyRunnable implements Runnable {
private static final ThreadLocal<Integer> var = ThreadLocal.withInitial(() -> 0);
private boolean removalStatus;
private int order;
public ThreadLocalMyRunnable(boolean removalStatus, int order) {
this.removalStatus = removalStatus;
this.order = order;
}
@Override
public void run() {
for (int i = 0; i < 5; i++) {
var.set(var.get() + 1);
String str = i == 0 ? " --init" : "";
System.out.println("Thread - " + order + " / " + " [" + i + "] " + " - " + var.get() + str);
}
if (removalStatus) {
var.remove();
}
}
}
public class ThreadLocalAfter {
public static void main(String[] args) {
for (int i = 0; i < 2; i++) {
Thread thread = new Thread(new ThreadLocalMyRunnable(false, i));
thread.start();
}
}
}
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadLocalRemoveBefore {
private static final ExecutorService executorService = Executors.newFixedThreadPool(3);
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
Thread thread = new Thread(new ThreadLocalMyRunnable(false, i));
executorService.execute(thread);
}
executorService.shutdown();
}
}
💡 Thread Pool
- 스레드 풀은 작업처리에 사용되는 Thread를 제한된 개수만큼 정해놓고 작업큐
(Queue)
에 들어오는 작업들을 하나씩 Thread가 맡아 처리하는 것- 생성된 Thread는 작업을 마치면 즉시 종료되지 않고, 대신 풀에 반환되어 다음 작업을 수행할 수 있도록 재사용된다. 즉, 종료된 Thread는 풀로 반환되기에 바로 GC의 대상이 되지 않아 GC 동작에 따른 오버헤드1가 감소된다.
- 여러 번 Runtime Data Area에 Thread를 생성하지 않고, 특정 수의 Thread를 미리 생성해 재사용함으로써 Thread의 생성 및 소멸에 따른 오버헤드를 최소화하고, 성능을 향상시킨다.
- Thread Pool을 사용하지 않고 필요 이상으로 Thread를 생성하면 메모리와 CPU 잠식2 문제가 발생할 수 있다.
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadLocalRemoveAfter {
private static final ExecutorService executorService = Executors.newFixedThreadPool(3);
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
Thread thread = new Thread(new ThreadLocalMyRunnable(true, i));
executorService.execute(thread);
}
executorService.shutdown();
}
}
💡참고