Java ThreadLocal ์์ธํ ์์๋ณด๊ธฐ
์ถ์ฒ: Devgenios ์ค๋์ Java ์ ํ๋ฆฌ์ผ์ด์ ๊ฐ๋ฐ์ ์ฌ์ฉ๋๋ ์ผ๋ฐ์ ์ธ ํด๋์ค ์ค ํ๋์ธ ThreadLocal์ ๋ํด ์์๋ด ๋๋ค.ThreadLocal์ด๋ ๋ฌด์์ ๋๊น?
ThreadLocal ํด๋์ค๋ ์ค๋ ๋์ ๋ํ ์ง์ญ ๋ณ์๋ฅผ ์ ์ฅํฉ๋๋ค. ์ด๋ฌํ ๋ณ์๋ ์๋ก ๋ค๋ฅธ ์ค๋ ๋ ๊ฐ์ ๊ฒฉ๋ฆฌ๋์ด ์์ผ๋ฉฐ ์์ฒด ์ค๋ ๋์์๋ง ์ก์ธ์คํ ์ ์์ต๋๋ค. ThreadLocal ์ฌ์ฉ ์ฌ๋ก :- ์ค๋ ๋ ๊ฐ ๋ฐ์ดํฐ๋ฅผ ๊ฒฉ๋ฆฌํฉ๋๋ค.
- ๋ฐ์ดํฐ๋ฒ ์ด์ค ์ฐ๊ฒฐ์ ์ํ ์ธ์ ๊ด๋ฆฌ.
- ์ค๋ ๋ ํธ๋์ญ์ ์ ๋ณด๋ฅผ ์ ์ฅํฉ๋๋ค.
ThreadLocal์ ์ด๋ป๊ฒ ์ฌ์ฉํ๋์?
๊ฐ๋จํ ์๋ฅผ ์ดํด๋ณด๊ฒ ์ต๋๋ค.public static void main(String[] args) {
//ะกะพะทะดะฐะตะผ ThreadLocal
ThreadLocal<String> local = new ThreadLocal<>();
//ะกะพะทะดะฐะตะผ ะฝะพะฒัะน ะบะปะฐัั Random
Random random = new Random();
//ะกะพะทะดะฐะตะผ 5 ะฟะพัะพะบะพะฒ
IntStream.range(0, 5).forEach(a-> new Thread(()-> {
//ะัะธัะฒะฐะธะฒะฐะตะผ meaning ะบะฐะถะดะพะผั ะฟะพัะพะบั
local.set(a+" "+random.nextInt(100));
System.out.println("Thread number and its local value "+ local.get());
}).start());
}
์ ์ฝ๋์์๋ ThreadLocal ํด๋์ค๋ฅผ ๋ง๋ค๊ณ , 5๊ฐ์ ์ค๋ ๋๋ฅผ ๋ง๋ค๊ณ , ๊ฐ ์ค๋ ๋์ ThreadLocal ์ ๊ฐ์ ํ ๋น ํ๊ณ ์ธ์ํฉ๋๋ค. ์ถ๋ ฅํ ๋ ์ฐ๋ฆฌ๋ ๋ค์์ ์ป์ต๋๋ค:
ํ๋ ์๋์๋ ๋ฌด์์ด ์๋์?
์์ธํ ์ดํด๋ณด๋ฉด ์ด ์ฝ๋ ์์ ์์ ThreadLocal ์ ๋ ๊ฐ์ง ์ค์ํ ๋ฉ์๋๊ฐ ์์ ์ ์ ์ ์์ต๋๋ค.-
๊ณต๊ฐ T get() {}
-
๊ณต๊ฐ ๋ฌดํจ ์งํฉ(T ๊ฐ) {}
public void set(T value) {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null)
map.set(this, value);
else
createMap(t, value);
}
setter ๋ฉ์๋๋ ๋จผ์ ํ์ฌ ์ค๋ ๋๋ฅผ ๊ฐ์ ธ์ค๊ณ getMap() ๋ฉ์๋๋ฅผ ํธ์ถํ์ฌ ThreadLocalMap ํด๋์ค๋ฅผ ๊ฐ์ ธ์ต๋๋ค . map์ด ์กด์ฌํ๋ ๊ฒฝ์ฐ ํ์ฌ ์คํธ๋ฆผ t๋ฅผ ํค๋ก, ์
๋ ฅ ๋งค๊ฐ๋ณ์๋ฅผ ๊ฐ์ผ๋ก ์ฌ์ฉํ๊ณ {key:value} ์์ map์ผ๋ก ์ค์ ํฉ๋๋ค. ๊ทธ๋ ์ง ์๋ค๋ฉด ์ง๋๋ฅผ ๋ง๋์ธ์ . ์ด์ ์ง๋ฌธ์ด ์๊ธธ ์ ์์ต๋๋ค. ThreadLocalMap์ด ๋ฌด์์ธ๊ฐ์ ?
static class ThreadLocalMap {
/**
* The entries in this hash map extend WeakReference, using
* its main ref field as the key (which is always a
* ThreadLocal object). Note that null keys (i.e. entry.get()
* == null) mean that the key is no longer referenced, so the
* entry can be expunged from table. Such entries are referred to
* as "stale entries" in the code that follows.
*/
static class Entry extends WeakReference<ThreadLocal<?>> {
/** The value associated with this ThreadLocal. */
Object value;
Entry(ThreadLocal<?> k, Object v) {
super(k);
value = v;
}
}
}
ThreadLocalMap์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๊ธฐ ์ํ Entry ํด๋์ค๋ฅผ ์ ์ํ๋ ThreadLocal ์ ๋ด๋ถ ์ ์ ํด๋์ค์
๋๋ค . Entry๋ ThreadLocal ์ธ์คํด์ค๋ฅผ ํค๋ก ์ฌ์ฉ ํ๊ณ ์ ๋ฌํ๋ ๊ฐ์ ์ค์ ํฉ๋๋ค. ์ด ์์ ์์ ์ด๊ฒ์ด ๋๋ฌด ํผ๋์ค๋ฝ๊ฒ ๋ค๋ฆฐ๋ค๋ฉด, ์ค์ ๋ก ๊ฐ์ ์ ์ฅํ๋ ๊ฒ์ ThreadLocalMap ์ Entry ํด๋์ค๋ผ๋ ์ ์ ๊ธฐ์ตํ์ธ์. ThreadLocal ์์ ๋ฐ์ดํฐ๋ฅผ ์ป์ผ๋ ค๋ฉด getter ๋ฉ์๋๋ฅผ ์ฌ์ฉํฉ๋๋ค .
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();
}
getter ๋ฉ์๋ ์์๋ currentThread๋ฅผ Key๋ก ์ฌ์ฉํ์ฌ ThreadLocalMap์ ๊ฐ์ ธ์ต๋๋ค . ๊ทธ๋ฐ ๋ค์ map์ ThreadLocal ์ธ์คํด์ค๋ฅผ ๊ธฐ๋ฐ์ผ๋ก getEntry()๋ฅผ ์ํ ํ๊ณ Entry ์ธ์คํด์ค ์ ์ ์ฅ๋ ๊ฐ์ ๋ฐํํฉ๋๋ค. ์ด๋ฅผ ์ดํดํ๋ ๋ฐ ๋์์ด ๋๋ ๋ค์ด์ด๊ทธ๋จ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
-
๊ฐ ์ค๋ ๋๋ ThreadLocalMap ์ ๋ํ ์ฐธ์กฐ๋ฅผ ์ ์งํฉ๋๋ค .
-
ThreadLocalMap์ ThreadLocal ์ ๋ด๋ถ ์ ์ ํด๋์ค ์ด๋ฉฐ ์ ์ฅ์ ์ํด Entry ํด๋์ค๋ฅผ ์ฌ์ฉํฉ๋๋ค .
-
ThreadLocalMap ํค๋ ThreadLocal์ ์ธ์คํด์ค ์ด๋ฉฐ ์ฌ๋ฌ ThreadLocal์ ๊ฐ์ง ์ ์์ต๋๋ค .
-
ThreadLocal ์์ฒด๋ ๊ฐ์ ์ ์ฅํ์ง ์์ง๋ง ThreadLocalMap ์์ ๊ฐ์ ๊ฐ์ ธ์ค๋ ๋ฐ ๋์์ด ๋๋ ์ค๋ ๋์ ํค์ ๋๋ค .
Java์ ์ค์บ๋ ํด๋์ค
์ถ์ฒ: Medium ์ด ๊ฒ์๋ฌผ์ Java์ Scanner ํด๋์ค์ ์ต์ํด์ง๋ ๋ฐ ๋์์ด ๋ ๊ฒ์ ๋๋ค. Java์ Scanner ํด๋์ค๋ ์ฌ์ฉ์๋ก๋ถํฐ ๊ฐ์ ์ป๊ณ ์ถ์ ๋ ์ฌ์ฉํ๋ ํด๋์ค์ ๋๋ค. ๊ฐ์ฅ ์ฝ๊ฒ ์ดํดํ๋ ๋ฐฉ๋ฒ์ ์์ ๋ฅผ ์ด์ฉํ๋ ๊ฒ์ด๋ฏ๋ก ์ข ๋ ๋ช ํํ๊ฒ ์ดํด๋ณด๊ฒ ์ต๋๋ค. Scanner ํด๋์ค๋ฅผ ์์ฑํ๋ ๊ฒ์ ์ฌ์ฉ์๋ก๋ถํฐ ๊ฐ์น๋ฅผ ์ป๊ธฐ ์ํด ์ทจํ๋ ์ธ ๋จ๊ณ ์ค ํ๋์ ๋๋ค. ์ฒซ ๋ฒ์งธ ๋จ๊ณ๋ ์ค์บ๋ ํด๋์ค์์ ๊ฐ์ฒด๋ฅผ ๋ง๋๋ ๊ฒ์ ๋๋ค.Scanner scan=new Scanner(System.in);
์ด์ ์ค์บ๋ ๊ฐ์ฒด๊ฐ ์๊ฒผ์ต๋๋ค. ์ด ๊ฐ์ฒด๋ Scanner ํด๋์ค ์ Scanner ์์ฑ์ ๊ฐ์ต๋๋ค . ์ฒซ ๋ฒ์งธ ๋จ๊ณ ์ดํ์๋ ์ด๋ฏธ ์ฌ์ฉ์๊ฐ ์ํ๋ ๊ฐ์ ์
๋ ฅํ ์ ์์ง๋ง, ์ฌ์ฉ์์๊ฒ ์๋ดํ์ง ์๊ณ ์ฝ์์ด๋ ์ ํ๋ฆฌ์ผ์ด์
์ ๊ทธ ๊ฐ์ ํ์ํ์ง ์๋๋ค๋ฉด ์ฌ์ฉ์ฑ ์ธก๋ฉด์์ ๊ทธ๋ค์ง ์ข์ง ์์ ๊ฒ์
๋๋ค. ๋ฐ๋ผ์ ์ฌ์ฉ์์๊ฒ ๋ค์ ์ฌํญ์ ์๋ฆฌ๊ณ ์๋ดํ๋ ๊ฒ์ด ์ข์ต๋๋ค.
System.out.println("Please enter your name");
String name=scan.next();
System.out.println("Your Name:"+name);
์ฒซ ๋ฒ์งธ ์ค์์ ์ฐ๋ฆฌ๋ ์ฌ์ฉ์์๊ฒ ์ฐ๋ฆฌ๊ฐ ์ํ๋ ๊ฒ์ด ๋ฌด์์ธ์ง ๋ฌป์ต๋๋ค. ์ด๋ ์ค์ ๋ก ์ค์บ๋์ ์๋ฌด ๊ด๋ จ์ด ์์ง๋ง ์ฌ์ฉ์์๊ฒ ํํธ๋ฅผ ์ ๊ณตํ๋ ๊ฒ์ด ํญ์ ์ข์ต๋๋ค. ๋ ๋ฒ์งธ ์ค์์๋ ์ฌ์ฉ์๊ฐ ๋ฐ์ดํฐ์ ์
๋ ฅํ๋ ๊ฐ์ ํ ๋นํ๊ณ ๋์ค์ ์ฌ์ฉํ ์ ์๋๋ก ์ ์ฅํฉ๋๋ค. ๋ง์ง๋ง ์ค์์๋ ์ฌ์ฉ์๋ก๋ถํฐ ๋ฐ์ ๊ฐ์ ์ฌ๋์ ๋ฐ๋ผ ์ฌ์ฉํ ์ ์์์ ์ ์ ์์ต๋๋ค. ์ฝ๋์ ๋ช ๊ฐ์ง ์ธ๋ถ์ ๋ณด๋ฅผ ์ถ๊ฐํด ๋ณด๊ฒ ์ต๋๋ค.
System.out.println("Please enter your last name");
String lastName=scan.next();
System.out.println("Your Name " + name + " " + "Your Last Name" + lastName);
๊ธฐ๋ณธ์ ์ผ๋ก ์ด์ ๋ ์ค์ ๋ฐ๋ณตํ๊ณ ์ฌ์ฉ์์๊ฒ ๊ฐ์ ์์ฒญํ ํ ์ ์ฅํ์ต๋๋ค. ์ด์ ๋ง์ง๋ง ์ค์์ ์ฐ๋ฆฌ๋ ์ฌ์ฉ์๋ก๋ถํฐ ๊ฐ์ ธ์์ ํจ๊ป ์ฌ์ฉ๋๋ ๋ ๊ฐ์ ๊ฐ์ ์ฌ์ฉํ์ต๋๋ค.
GO TO FULL VERSION