๐[Java] ๋์์ฑ ๋ฌธ์ ๋?
๋์์ฑ ๋ฌธ์ ๊ฐ ๋ญ๊น?
๋์์ ๊ฐ์๋ฅผ ๋ฃ๋ ์ค, ๋์์ฑ ๋ฌธ์
๋ผ๋ ๊ฒ์ด ๋์๋ค.
๋์์ฑ ๋ฌธ์ ๊ฐ ๋ญ์ง ๋ชฐ๋ผ์ ์ฐพ์๋ณด๊ฒ ๋์๋ค.
๋์์ฑ ๋ฌธ์ ๋
๋์์ฑ ๋ฌธ์
๋ ์ฌ๋ฌ ์ค๋ ๋๊ฐ ๋์์ ๊ฐ์ ์ธ์คํด์ค์ ํ๋ ๊ฐ์ โ๋ณ๊ฒฝโํ๋ฉด์ ๋ฐ์ํ๋ ๋ฌธ์ ๋ฅผ ๋งํ๋ค.
์ด๋ฐ ๋์์ฑ ๋ฌธ์ ๋ ์ฌ๋ฌ ์ค๋ ๋๊ฐ ๊ฐ์ ์ธ์คํด์ค์ ํ๋์ ์ ๊ทผํด์ผ ํ๊ธฐ ๋๋ฌธ์ ํธ๋ํฝ์ด ์ ์ ์ํฉ์์๋ ํ๋ฅ ์ ์ ๋ํ๋์ง ์์ง๋ง, ํธ๋ํฝ์ด ๋ง์์ง ์๋ก ๋ฐ์ ํ๋ฅ ์ด ๋์์ง๋ค.
ํนํ ์คํ๋ง ๋น ์ฒ๋ผ โ์ฑ๊ธํคโ ๊ฐ์ฒด์ ํ๋๋ฅผ ๋ณ๊ฒฝํ๋ฉฐ ์ฌ์ฉํ ๋ ์ด๋ฌํ ๋์์ฑ ๋ฌธ์ ๋ฅผ ์กฐ์ฌํ์!
์ฐธ๊ณ
๋์์ฑ ๋ฌธ์ ๋ ์ง์ญ๋ณ์
์์๋ ๋ฐ์ํ์ง ์๋๋ค.
์๋ํ๋ฉด ์ง์ญ๋ณ์๋ ์ค๋ ๋๋ง๋ค ๊ฐ๊ฐ ๋ค๋ฅธ ๋ฉ๋ชจ๋ฆฌ ์์ญ์ด ํ ๋น๋๊ธฐ ๋๋ฌธ!
๊ทธ๋ฆฌ๊ณ static๊ฐ์ ๊ณต์ฉ ํ๋์ ์ ๊ทผํ ๋ ๋ฐ์ํ ์ ์์.
ํ์ง๋ง ๋์์ฑ ๋ฌธ์ ๋ ๊ฐ์ ์ฝ๊ธฐ๋ง ํ๋ฉด
๋ฐ์ํ์ง ์๊ณ , ์ด๋์ ๊ฐ ๊ฐ์ ๋ณ๊ฒฝ
ํด์ผ ๋ฐ์ํ๋ค!
์์ ์ฝ๋
package hello.advanced.trace.threadlocal;
import hello.advanced.trace.threadlocal.code.FieldService;
import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;
@Slf4j
public class FieldServiceTest {
private FieldService fieldService = new FieldService();
@Test
void field() {
log.info("main start");
Runnable userA = () -> {
fieldService.logic("userA");
};
Runnable userB = () -> {
fieldService.logic("userB");
};
Thread threadA = new Thread(userA);
threadA.setName("thread A");
Thread threadB = new Thread(userB);
threadB.setName("thread B");
threadA.start();
// sleep(2000); // ๋์์ฑ ๋ฌธ์ ๋ฐ์ x
sleep(100);
threadB.start();
sleep(3000); // ๋ฉ์ธ ์ค๋ ๋ ์ข
๋ฃ ๋๊ธฐ
log.info("main exit");
}
private void sleep(int millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
sleep(2000);์ผ๋ก ํ๋ฉด ๋์์ฑ ๋ฌธ์ ๊ฐ ๋ฐ์ํ์ง ์๋๋ค.
ํ์ง๋ง sleep(100);์ผ๋ก ํ๋ฉด ๋งค์ฐ ์งง์ ์๊ฐ ๋์๋ง sleep์ ํ๊ธฐ ๋๋ฌธ์ ๋์์ฑ ๋ฌธ์ ๊ฐ ๋ฐ์ํ๋ค.
[๊ฒฐ๊ณผ]
00:51:26.619 [Test worker] INFO hello.advanced.trace.threadlocal.FieldServiceTest - main start
00:51:26.622 [thread A] INFO hello.advanced.trace.threadlocal.code.FieldService - ์ ์ฅ name=userA --> nameStore=null
00:51:26.727 [thread B] INFO hello.advanced.trace.threadlocal.code.FieldService - ์ ์ฅ name=userB --> nameStore=userA
00:51:27.628 [thread A] INFO hello.advanced.trace.threadlocal.code.FieldService - ์กฐํ namrStore=userB
00:51:27.733 [thread B] INFO hello.advanced.trace.threadlocal.code.FieldService - ์กฐํ namrStore=userB
00:51:29.733 [Test worker] INFO hello.advanced.trace.threadlocal.FieldServiceTest - main exit
์๋๋ nameStore์ userA๊ฐ ๋ค์ด๊ฐ์ผ ํ๋๋ฐ, sleep์๊ฐ์ด ๋งค์ฐ ์งง์ userA์์
์ด ๋๋๊ธฐ๋ ์ ์ userB๊ฐ ์น๊ณ ๋ค์ด์๋ค.
๊ทธ๋์ nameStore์ ์๋ ์ต์ ๊ฐ์ userB์ด๊ณ , userA์ ์์
์ด ์๋ฃ๋์ด return์ ๋ฐ๋๋ฐ nameStore์ ๋ค์ด์๋ ๊ฐ์ userB๋ผ์ userA๊ฐ userB๋ฅผ ๋ฆฌํด๋ฐ๋ ๊ฒฝ์ฐ๊ฐ ๋ฐ์ํ๋ค.
์์๋๋ก ์ ๋ฆฌ
- threadA๋ userA๋ฅผ nameStore์ ์ ์ฅ.
- threadB๋ userB๋ฅผ nameStore์ ์ ์ฅ.
- threadA๋ userB๋ฅผ nameStore์ ์กฐํ.
- threadB๋ userB๋ฅผ nameStore์ ์กฐํ.
๋์์ฑ ๋ฌธ์ ํด๊ฒฐ - ThreadLocal
ThreadLocal
์ ํด๋น ์ฐ๋ ๋๋ง ์ ๊ทผํ ์ ์๋ ํน๋ณํ ์ ์ฅ์ ๋ฅผ ์๋ฏธํ๋ค.
์ฝ๊ฒ ์๊ฐํ๋ฉด, ๋ฌผ๊ฑด์ ๋ณด๊ดํ ์ ์๋ ์ฐฝ๊ตฌ๋ฅผ ์๊ฐํ ์ ์๋ค.
์ฌ๋ฌ ์ฌ๋์ด ๋ฌผ๊ฑด์ ๋ณด๊ดํ๊ฒ ๋๋ฉด, ์ง์์ด ์ฌ์ฉ์๋ง๋ค ๋ฌผ๊ฑด์ ๋ณด๊ดํ ์ ์๋ ๊ฐ๋ณ ๋ณด๊ดํจ์ ๋ฌผ๊ฑด์ ๋ณด๊ดํ๊ณ ๊บผ๋ธ๋ค.
์ค๋ ๋ ๋ก์ปฌ
์ ์ฌ์ฉํ๋ฉด ๊ฐ ์ค๋ ๋๋ง๋ค ๋ณ๋์ ๋ด๋ถ ์ ์ฅ์๋ฅผ ์ ๊ณตํ๊ธฐ ๋๋ฌธ์, ๊ฐ์ ์ธ์คํด์ค์ ์ค๋ ๋ ๋ก์ปฌ ํ๋์ ์ ๊ทผํด๋ ๋ฌธ์ ๊ฐ ์๋ค.
์ฐธ๊ณ
์๋ฐ์์๋ ์ธ์ด ์ฐจ์์์ ์ค๋ ๋ ๋ก์ปฌ์ ์ง์ํ๊ธฐ ์ํด java.lang.ThreadLocal
ํด๋์ค๋ฅผ ์ ๊ณตํจ!
ThreadLocal ์ฌ์ฉ๋ฒ
- ๊ฐ ์ ์ฅ: ThreadLocal.set()
- ๊ฐ ์กฐํ: ThreadLocal.get()
- ๊ฐ ์ญ์ : ThreadLocal.remove()
์ฃผ์: ํด๋น ์ค๋ ๋๊ฐ ์ค๋ ๋ ๋ก์ปฌ์ ๋ชจ๋ ์ฌ์ฉํ๊ณ ๋๋ฉด
ThreadLocal.remove()
๋ฅผ ํธ์ถํด์ ์ค๋ ๋ ๋ก์ปฌ์ ์ ์ฅ๋ ๊ฐ์ ์ ๊ฑฐํด์ฃผ์ด์ผ ํจ!
๊ฒฐ๊ณผ์ ์ผ๋ก!
์ค๋ ๋ ๋ก์ปฌ ๋๋ถ์ ์ค๋ ๋ ๋ณ๋ก ๋ณ๋์ ์ ์ฅ๊ณต๊ฐ์ ๊ฐ๊ฒ ๋์๋ค! -> ๋์์ฑ ๋ฌธ์ ํด๊ฒฐ!
ThreadLocal ์ฃผ์์ฌํญ
์ค๋ ๋ ๋ก์ปฌ์ ๊ฐ์ ์ ๊ฑฐํ์ง ์๊ณ ๊ทธ๋ฅ ๋๋ฉด WAS(ํฐ์บฃ)์ฒ๋ผ ์ค๋ ๋ ํ
์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ์ ์ฌ๊ฐํ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์๋ค.
[์ฌ์ฉ์A์ ์์ฒญ]
- ์ฌ์ฉ์ A๊ฐ ์ ์ฅ http์์ฒญ์ ๋ณด๋
- WAS๋ ์ค๋ ๋ ํ์์ ์ค๋ ๋๋ฅผ ํ๋ ์กฐํํจ
- ์ค๋ ๋
thread-A
๊ฐ ํ ๋น๋จ thread-A
๋ ์ฌ์ฉ์ A์ ์ ๋ณด๋ฅผ ์ค๋ ๋ ๋ก์ปฌ์ ์ ์ฅํจ- ์ค๋ ๋ ๋ก์ปฌ์
thread-A
์ ์ฉ ์ ์ฅ์์ ์ฌ์ฉ์ A์ ์ ๋ณด๋ฅผ ์ ์ฅํจ
[์ฌ์ฉ์A์ ์์ฒญ ์ข
๋ฃ]
- ์ฌ์ฉ์A์ HTTP ์๋ต์ด ๋๋จ
- WAS๋ ์ฌ์ฉ์ด ๋๋
thread-A
๋ฅผ ์ฐ๋ ๋ ํ์ ๋ฐํํ๋ค. ์ฐ๋ ๋๋ฅผ ์์ฑํ๋ ๋น์ฉ์ ๋น์ธ๊ธฐ ๋๋ฌธ์ ์ฐ๋ ๋๋ฅผ ์ ๊ฑฐํ์ง ์๊ณ , ๋ณดํต ์ฐ๋ ๋ ํ์ ํตํด์ ์ฐ๋ ๋๋ฅผ ์ฌ์ฌ์ฉํจ thread-A
๋ ์ฐ๋ ๋ํ์ ์์ง ์ด์์๋ค. ๋ฐ๋ผ์ ์ฐ๋ ๋ ๋ก์ปฌ์thread-A
์ ์ฉ ๋ณด๊ด์์์ฌ์ฉ์A
๋ฐ์ดํฐ๋ ํจ๊ป ์ด์์๊ฒ ๋๋ค.
[์ฌ์ฉ์B์ ์์ฒญ]
- ์ฌ์ฉ์B๊ฐ ์กฐํ๋ฅผ ์ํ ์๋ก์ด HTTP ์์ฒญ์ ๋ณด๋
- WAS๋ ์ฐ๋ ๋ ํ์์ ์ฐ๋ ๋๋ฅผ ํ๋ ์กฐํํจ
- ์ฐ๋ ๋
thread-A
๊ฐ ํ ๋น๋์๋ค. (๋ฌผ๋ก ๋ค๋ฅธ ์ฐ๋ ๋๊ฐ ํ ๋น๋ ์ ๋ ์๋ค.) - ์ด๋ฒ์๋ ์กฐํํ๋ ์์ฒญ์ด๋ค.
thread-A
๋ ์ฐ๋ ๋ ๋ก์ปฌ์์ ๋ฐ์ดํฐ๋ฅผ ์กฐํํ๋ค. - ์ฐ๋ ๋ ๋ก์ปฌ์
thread-A
์ ์ฉ ๋ณด๊ด์์ ์๋์ฌ์ฉ์A
๊ฐ์ ๋ฐํํ๋ค. - ๊ฒฐ๊ณผ์ ์ผ๋ก
์ฌ์ฉ์A
๊ฐ์ด ๋ฐํ๋๋ค. - ์ฌ์ฉ์B๋
์ฌ์ฉ์A
์ ์ ๋ณด๋ฅผ ์กฐํํ๊ฒ ๋๋ค.
์์ฒ๋ผ ๋ณด์์ ์ธ ์ธก๋ฉด์์ ์ฌ๊ฐํ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์์ผ๋ฏ๋ก, ์ฌ์ฉ์A์ ์์ฒญ์ด ๋๋ ๋ ๋ฐ๋์ ThreadLocal.remove()
๋ฅผ ํตํด ๊ผญ ์ ๊ฑฐํด์ฃผ์.
๋๊ธ๋จ๊ธฐ๊ธฐ