์ด ๋จ์์์๋ java.lang.ThreadLocal<> ํด๋์ค ์์ ๊ณผ ๋ค์ค ์ค๋ ๋ ํ๊ฒฝ์์ ์ด๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ ์ ๋ํด ์ผ๋ฐ์ ์ผ๋ก ์ค๋ช ํฉ๋๋ค .
ThreadLocal ํด๋์ค๋ ๋ณ์๋ฅผ ์ ์ฅํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. ์ด ํด๋์ค์ ํน์ง์ ์ด๋ฅผ ์ฌ์ฉํ๋ ๊ฐ ์ค๋ ๋์ ๋ํ ๊ฐ์ ๋ณ๋์ ๋ ๋ฆฝ์ ์ธ ๋ณต์ฌ๋ณธ์ ์ ์งํ๋ค๋ ๊ฒ์ ๋๋ค.
ํด๋์ค์ ์๋์ ๋ ๊น์ด ํ๊ณ ๋ค๋ฉด ์ค๋ ๋๋ฅผ ๊ฐ์ ๋งคํํ๋ ๋งต์ ์์ํ ์ ์์ต๋๋ค. ํ์ฌ ์ค๋ ๋๋ ์ด๋ฅผ ์ฌ์ฉํด์ผ ํ ๋ ์ ์ ํ ๊ฐ์ ๊ฐ์ ธ์ต๋๋ค.
ThreadLocal ํด๋์ค ์์ฑ์
๊ฑด์ค์ | ํ๋ |
---|---|
์ค๋ ๋๋ก์ปฌ() | Java์์ ๋น ๋ณ์๋ฅผ ์์ฑํฉ๋๋ค. |
ํ๋ ์์
๋ฐฉ๋ฒ | ํ๋ |
---|---|
์ป๋ค() | ํ์ฌ ์ค๋ ๋์ ์ง์ญ ๋ณ์ ๊ฐ์ ๋ฐํํฉ๋๋ค. |
์ธํธ() | ํ์ฌ ์ค๋ ๋์ ๋ํ ์ง์ญ ๋ณ์์ ๊ฐ์ ์ค์ ํฉ๋๋ค. |
์ ๊ฑฐํ๋ค() | ํ์ฌ ์ค๋ ๋์ ์ง์ญ ๋ณ์ ๊ฐ์ ์ ๊ฑฐํฉ๋๋ค. |
ThreadLocal.withInitial() | ์ด๊ธฐ๊ฐ์ ์ค์ ํ๋ ์ถ๊ฐ์ ์ธ ํฉํ ๋ฆฌ ๋ฉ์๋ |
get() ๋ฐ ์ค์ ()
๋ ๊ฐ์ ์นด์ดํฐ๋ฅผ ๋ง๋๋ ์์ ๋ฅผ ์์ฑํด ๋ณด๊ฒ ์ต๋๋ค. ์ฒซ ๋ฒ์งธ ์ผ๋ฐ ๋ณ์๋ ์ค๋ ๋ ์๋ฅผ ๊ณ์ฐํ๊ธฐ ์ํ ๊ฒ์ ๋๋ค. ๋ ๋ฒ์งธ๋ ThreadLocal ๋ก ๋ํํฉ๋๋ค . ๊ทธ๋ฆฌ๊ณ ์ฐ๋ฆฌ๋ ๊ทธ๋ค์ด ์ด๋ป๊ฒ ํจ๊ป ์๋ํ๋์ง ๋ณผ ๊ฒ์ ๋๋ค. ๋จผ์ Runnable์ ์์ ํ๊ณ ๋ฐ์ดํฐ์ ๊ฐ์ฅ ์ค์ํ run() ๋ฉ์๋๋ฅผ ํฌํจํ๋ ThreadDemo ํด๋์ค๋ฅผ ์์ฑํด ๋ณด๊ฒ ์ต๋๋ค . ๋ํ ํ๋ฉด์ ์นด์ดํฐ๋ฅผ ํ์ํ๋ ๋ฐฉ๋ฒ๋ ์ถ๊ฐํฉ๋๋ค.
class ThreadDemo implements Runnable {
int counter;
ThreadLocal<Integer> threadLocalCounter = new ThreadLocal<>();
public void run() {
counter++;
if(threadLocalCounter.get() != null) {
threadLocalCounter.set(threadLocalCounter.get() + 1);
} else {
threadLocalCounter.set(0);
}
printCounters();
}
public void printCounters(){
System.out.println("Counter: " + counter);
System.out.println("threadLocalCounter: " + threadLocalCounter.get());
}
}
์์ ์ด ์งํ๋ ๋๋ง๋ค ์ฐ๋ฆฌ๋์นด์ดํฐ๋ณ์๋ get() ๋ฉ์๋๋ฅผ ํธ์ถํ์ฌ ThreadLocal ๋ณ์ ์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ต๋๋ค . ์ ์ค๋ ๋์ ๋ฐ์ดํฐ๊ฐ ์์ผ๋ฉด 0์ผ๋ก ์ค์ ํฉ๋๋ค. ๋ฐ์ดํฐ๊ฐ ์์ผ๋ฉด 1์ฉ ๋๋ฆฝ๋๋ค. ๊ทธ๋ฆฌ๊ณ ์ฐ๋ฆฌ์ ์ฃผ์ ๋ฐฉ๋ฒ์ ์์ฑํด ๋ด ์๋ค .
public static void main(String[] args) {
ThreadDemo threadDemo = new ThreadDemo();
Thread t1 = new Thread(threadDemo);
Thread t2 = new Thread(threadDemo);
Thread t3 = new Thread(threadDemo);
t1.start();
t2.start();
t3.start();
}
ํด๋์ค๋ฅผ ์คํํ๋ฉด ThreadLocal ๋ณ์๋ ์ก์ธ์คํ๋ ์ค๋ ๋์ ๊ด๊ณ์์ด ๋์ผํ๊ฒ ์ ์ง๋์ง๋ง ์ค๋ ๋ ์๋ ์ฆ๊ฐํฉ๋๋ค.
์นด์ดํฐ: 2
์นด์ดํฐ: 3
threadLocalCounter: 0
threadLocalCounter: 0
threadLocalCounter: 0
ํ๋ก์ธ์ค๊ฐ ์ข ๋ฃ ์ฝ๋ 0์ผ๋ก ์ข ๋ฃ๋จ
์ ๊ฑฐํ๋ค()
remove ๋ฉ์๋์ ์๋ ๋ฐฉ์์ ์ดํดํ๊ธฐ ์ํด ThreadDemo ํด๋์ค ์ ์ฝ๋๋ฅผ ์ฝ๊ฐ ๋ณ๊ฒฝํฉ๋๋ค .
if(threadLocalCounter.get() != null) {
threadLocalCounter.set(threadLocalCounter.get() + 1);
} else {
if (counter % 2 == 0) {
threadLocalCounter.remove();
} else {
threadLocalCounter.set(0);
}
}
์ด ์ฝ๋์์ ์ค๋ ๋ ์นด์ดํฐ๊ฐ ์ง์์ด๋ฉด ThreadLocal ๋ณ์ ์์ remove() ๋ฉ์๋๋ฅผ ํธ์ถํฉ๋๋ค . ๊ฒฐ๊ณผ:
threadLocalCounter: 0
์นด์ดํฐ: 2
threadLocalCounter: null
์นด์ดํฐ: 1
threadLocalCounter: 0
ํ๋ก์ธ์ค๊ฐ ์ข ๋ฃ ์ฝ๋ 0์ผ๋ก ์ข ๋ฃ๋จ
์ฌ๊ธฐ์ ์ฐ๋ฆฌ๋ ๋ ๋ฒ์งธ ์ค๋ ๋์ ThreadLocal ๋ณ์๊ฐ null ์์ ์ฝ๊ฒ ์ ์ ์์ต๋๋ค .
ThreadLocal.withInitial()
์ด ๋ฉ์๋๋ ์ค๋ ๋ ๋ก์ปฌ ๋ณ์๋ฅผ ๋ง๋ญ๋๋ค.
ThreadDemo ํด๋์ค ๊ตฌํ :
class ThreadDemo implements Runnable {
int counter;
ThreadLocal<Integer> threadLocalCounter = ThreadLocal.withInitial(() -> 1);
public void run() {
counter++;
printCounters();
}
public void printCounters(){
System.out.println("Counter: " + counter);
System.out.println("threadLocalCounter: " + threadLocalCounter.get());
}
}
๊ทธ๋ฆฌ๊ณ ์ฝ๋์ ๊ฒฐ๊ณผ๋ฅผ ๋ณผ ์ ์์ต๋๋ค.
์นด์ดํฐ: 2
์นด์ดํฐ: 3
threadLocalCounter: 1
threadLocalCounter: 1
threadLocalCounter: 1
ํ๋ก์ธ์ค๊ฐ ์ข ๋ฃ ์ฝ๋ 0์ผ๋ก ์ข ๋ฃ๋จ
์ ๊ทธ๋ฐ ๋ณ์๋ฅผ ์ฌ์ฉํด์ผ ํฉ๋๊น?
ThreadLocal์ java.lang.Thread ์คํ ์ค๋ ๋์ ๊ด๋ จํ์ฌ ๋ก์ปฌ ๋ณ์์ ๋ํ ์ถ์ํ๋ฅผ ์ ๊ณตํฉ๋๋ค.
ThreadLocal ๋ณ์๋ ๊ฐ ์ค๋ ๋๊ฐ get() ๋ฐ set() ๋ฉ์๋ ๋ฅผ ํตํด ์ก์ธ์คํ ์ ์๋ ๊ฐ๋ณ์ ์ผ๋ก ์ด๊ธฐํ๋ ์์ฒด ๋ณ์ ์ธ์คํด์ค๋ฅผ ๊ฐ๋๋ค๋ ์ ์์ ์ผ๋ฐ ๋ณ์์ ๋ค๋ฆ ๋๋ค.
๊ฐ ์ค๋ ๋, ์ฆ Thread ํด๋์ค์ ์ธ์คํด์ค ์๋ ์ฐ๊ฒฐ๋ ThreadLocal ๋ณ์ ์ ๋งต์ด ์์ต๋๋ค . ๋งต์ ํค๋ ThreadLocal ๊ฐ์ฒด ์ ๋ํ ์ฐธ์กฐ ์ด๊ณ ๊ฐ์ "ํ๋ํ" ThreadLocal ๋ณ์์ ๋ํ ์ฐธ์กฐ์ ๋๋ค.
Random ํด๋์ค๊ฐ ๋ค์ค ์ค๋ ๋ ์์ฉ ํ๋ก๊ทธ๋จ์์ ๋์๋ฅผ ์์ฑํ๋ ๋ฐ ์ ํฉํ์ง ์์ ์ด์ ๋ ๋ฌด์์ ๋๊น?
Random ํด๋์ค๋ฅผ ์ฌ์ฉํ์ฌ ๋์๋ฅผ ์ป์ต๋๋ค. ํ์ง๋ง ๋ฉํฐ์ค๋ ๋ ํ๊ฒฝ์์๋ ์ ๋๋ก ์๋ํ ๊น์? ์ฌ์ค, ์๋์ค. Random์ ๋ค์ค ์ค๋ ๋ ํ๊ฒฝ์ ์ ํฉํ์ง ์์ต๋๋ค. ์ฌ๋ฌ ์ค๋ ๋๊ฐ ๋์์ ํด๋์ค์ ์ก์ธ์คํ๋ฉด ์ฑ๋ฅ์ด ์ ํ๋๊ธฐ ๋๋ฌธ์ ๋๋ค.
์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด JDK 7์์๋ ๋ค์ค ์ค๋ ๋ ํ๊ฒฝ์์ ๋์๋ฅผ ์์ฑํ๋ java.util.concurrent.ThreadLocalRandom ํด๋์ค๋ฅผ ๋์ ํ์ต๋๋ค. ThreadLocal ๋ฐ Random ์ ๋ ํด๋์ค๋ก ๊ตฌ์ฑ๋ฉ๋๋ค .
ํ ์ค๋ ๋์์ ์์ ํ ๋์๋ ๋ค๋ฅธ ์ค๋ ๋์ ๋ ๋ฆฝ์ ์ด์ง๋ง java.util.Random์ ์ ์ญ์ ์ผ๋ก ๋์๋ฅผ ์ ๊ณตํฉ๋๋ค. ๋ํ Random ๊ณผ ๋ฌ๋ฆฌ ThreadLocalRandom์ ๋ช ์์ ์๋๋ฅผ ์ง์ํ์ง ์์ต๋๋ค. ๋์ Random ์์ ์์๋ setSeed() ๋ฉ์๋๋ฅผ ์ฌ์ ์ํ๋ฏ๋ก ํธ์ถ ์ ํญ์ UnsupportedOperationException์ด ๋ฐ์ ํฉ๋๋ค .
ThreadLocalRandom ํด๋์ค ์ ๋ฉ์๋๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค .
๋ฐฉ๋ฒ | ํ๋ |
---|---|
ThreadLocalRandom ์ ๋ฅ() | ํ์ฌ ์ค๋ ๋์ ThreadLocalRandom์ ๋ฐํํฉ๋๋ค. |
์ ์ ๋ค์(์ ์ ๋นํธ) | ๋ค์ ์์ฌ ๋์๋ฅผ ์์ฑํฉ๋๋ค. |
double nextDouble(๋๋ธ ์ต์, ๋๋ธ ๋ฐ์ด๋) | ์ต์ (ํฌํจ)์ ๋ฐ์ด๋ (์ ์ธ) ์ฌ์ด์ ๊ท ๋ฑ ๋ถํฌ์์ ์์ฌ ๋์๋ฅผ ๋ฐํํฉ๋๋ค . |
int nextInt(์ ์ด๋ ์ ์, ๊ฒฝ๊ณ ์ ์) | ์ต์(ํฌํจ)์ ๋ฐ์ด๋(์ ์ธ) ์ฌ์ด์ ๊ท ๋ฑ ๋ถํฌ์์ ์์ฌ ๋์๋ฅผ ๋ฐํํฉ๋๋ค. |
๊ธด nextLong(๊ธด n) | 0(ํฌํจ)๊ณผ ์ง์ ๋ ๊ฐ(์ ์ธ) ์ฌ์ด์ ๊ท ์ผ ๋ถํฌ์์ ์์ฌ ๋์๋ฅผ ๋ฐํํฉ๋๋ค. |
๊ธด nextLong(๊ธด ์ต์, ๊ธด ๊ฒฝ๊ณ) | ์ต์(ํฌํจ)์ ๋ฐ์ด๋(์ ์ธ) ์ฌ์ด์ ๊ท ๋ฑ ๋ถํฌ์์ ์์ฌ ๋์๋ฅผ ๋ฐํํฉ๋๋ค. |
๋ฌดํจ setSeed(๊ธด ์๋) | UnsupportedOperationException ์ ๋์ง๋๋ค . ์ด ์์ฑ๊ธฐ๋ ์๋๋ฅผ ์ง์ํ์ง ์์ต๋๋ค. |
ThreadLocalRandom.current()๋ฅผ ์ฌ์ฉํ์ฌ ๋์ ์ป๊ธฐ
ThreadLocalRandom์ ThreadLocal ๊ณผ Random ํด๋์ค ์ ์กฐํฉ์ ๋๋ค. Random ํด๋์ค ์ ์ธ์คํด์ค์ ๋ํ ๋์ ์ก์ธ์ค๋ฅผ ๋จ์ํ ํผํจ์ผ๋ก์จ ๋ค์ค ์ค๋ ๋ ํ๊ฒฝ์์ ๋ ๋์ ์ฑ๋ฅ์ ์ป์ต๋๋ค.
์ฌ๋ฌ ์ค๋ ๋๊ฐ ํฌํจ๋ ์์ ๋ฅผ ๊ตฌํํ๊ณ ์์ฉ ํ๋ก๊ทธ๋จ์ด ThreadLocalRandom ํด๋์ค๋ก ์ํํ๋ ๊ฒ์ ์ดํด๋ณด๊ฒ ์ต๋๋ค.
import java.util.concurrent.ThreadLocalRandom;
class RandomNumbers extends Thread {
public void run() {
try {
int bound = 100;
int result = ThreadLocalRandom.current().nextInt(bound);
System.out.println("Thread " + Thread.currentThread().getId() + " generated " + result);
}
catch (Exception e) {
System.out.println("Exception");
}
}
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
for (int i = 0; i < 10; i++) {
RandomNumbers randomNumbers = new RandomNumbers();
randomNumbers.start();
}
long endTime = System.currentTimeMillis();
System.out.println("Time taken: " + (endTime - startTime));
}
}
์ฐ๋ฆฌ ํ๋ก๊ทธ๋จ์ ๊ฒฐ๊ณผ:
์ค๋ ๋ 17 ์์ฑ 13
์ค๋ ๋ 18 ์์ฑ 41
์ค๋ ๋ 16 ์์ฑ 99
์ค๋ ๋ 19 ์์ฑ 25
์ค๋ ๋ 23 ์์ฑ 33
์ค๋ ๋ 24 ์์ฑ 21
์ค๋ ๋ 15 ์์ฑ 15
์ค๋ ๋ 21 ์์ฑ 28
์ค๋ ๋ 22 ์์ฑ 97
์ค๋ ๋ 20 ์์ฑ 33
์ด์ RandomNumbers ํด๋์ค๋ฅผ ๋ณ๊ฒฝํ๊ณ Random์ ์ฌ์ฉํ๊ฒ ์ต๋๋ค .
int result = new Random().nextInt(bound);
์ค๋ ๋ 20 ์์ฑ 48
์ค๋ ๋ 19 ์์ฑ 57
์ค๋ ๋ 18 ์์ฑ 90
์ค๋ ๋ 22 ์์ฑ 43
์ค๋ ๋ 24 ์์ฑ 7
์ค๋ ๋ 23 ์์ฑ 63
์ค๋ ๋ 15 ์์ฑ 2
์ค๋ ๋ 16 ์์ฑ 40
์ค๋ ๋ 17 ์์ฑ 29
์ค๋ ๋ 21 ์์ฑ 12
ํ๊ธฐ ํด! ํ ์คํธ์์ ๊ฒฐ๊ณผ๊ฐ ๊ฐ์ ๋๋ ์๊ณ ๋ค๋ฅผ ๋๋ ์์์ต๋๋ค. ๊ทธ๋ฌ๋ ๋ ๋ง์ ์ค๋ ๋(์: 100)๋ฅผ ์ฌ์ฉํ๋ฉด ๊ฒฐ๊ณผ๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
๋ฌด์์ โ 19-25ms
ThreadLocalRandom โ 17-19ms ๋ฐ๋ผ์ ์์ฉ ํ๋ก๊ทธ๋จ์ ์ค๋ ๋๊ฐ ๋ง์์๋ก ๋ค์ค ์ค๋ ๋ ํ๊ฒฝ์์ Random ํด๋์ค ๋ฅผ ์ฌ์ฉํ ๋ ์ฑ๋ฅ ์ ํ๊ฐ ์ปค์ง๋๋ค . |
Random ํด๋์ค ์ ThreadLocalRandom ํด๋์ค ๊ฐ์ ์ฐจ์ด์ ์ ์์ฝํ๊ณ ๋ฐ๋ณตํ๋ ค๋ฉด ๋ค์์ ์ํํ์ญ์์ค .
๋ฌด์์์ | ์ค๋ ๋๋ก์ปฌ๋๋ค |
---|---|
๋ค๋ฅธ ์ค๋ ๋๊ฐ ๋์ผํ Random ์ธ์คํด์ค๋ฅผ ์ฌ์ฉํ๋ฉด ์ถฉ๋์ด ๋ฐ์ํ๊ณ ์ฑ๋ฅ์ด ์ ํ๋ฉ๋๋ค. | ์์ฑ๋ ๋์๊ฐ ํ์ฌ ์ค๋ ๋์ ๋ก์ปฌ์ด๊ธฐ ๋๋ฌธ์ ์ถฉ๋์ด๋ ๋ฌธ์ ๊ฐ ์์ต๋๋ค. |
์ ํ ํฉ๋ ๊ณต์์ ์ฌ์ฉํ์ฌ ์ด๊ธฐ๊ฐ์ ๋ณ๊ฒฝํฉ๋๋ค. | ๋์ ์์ฑ๊ธฐ๋ ๋ด๋ถ์ ์ผ๋ก ์์ฑ๋ ์๋๋ฅผ ์ฌ์ฉํ์ฌ ์ด๊ธฐํ๋ฉ๋๋ค. |
๊ฐ ์ค๋ ๋๊ฐ ๊ณ ์ ํ Random ๊ฐ์ฒด ์งํฉ์ ์ฌ์ฉํ๋ ์์ฉ ํ๋ก๊ทธ๋จ์ ์ ์ฉํฉ๋๋ค . | ์ฌ๋ฌ ์ค๋ ๋๊ฐ ์ค๋ ๋ ํ์์ ๋ณ๋ ฌ๋ก ๋์๋ฅผ ์ฌ์ฉํ๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ์ ์ฉํฉ๋๋ค. |
์ด๊ฒ์ ๋ถ๋ชจ ํด๋์ค์ ๋๋ค. | ์ด๊ฒ์ ์์ ํด๋์ค์ ๋๋ค. |
GO TO FULL VERSION