ThreadLocal

Java ThreadLocal은 Java 1.2λΆ€ν„° λ„μž…λ˜μ—ˆλ‹€. Key, Value둜 κ΅¬μ„±λ˜μ–΄ 있음

  • Key : Current Thread

  • Value : Any Object

ThreadLocal은 각 μŠ€λ ˆλ“œλ§ˆλ‹€ 독립적인 값을 μ €μž₯ν•  수 있게 ν•΄μ£ΌλŠ” ν΄λž˜μŠ€μ΄λ‹€. λ‹€μ‹œ 말해, λ™μΌν•œ ThreadLocal 객체λ₯Ό μ—¬λŸ¬ μŠ€λ ˆλ“œκ°€ κ³΅μœ ν•˜λ”λΌλ„ 각 μŠ€λ ˆλ“œλŠ” μžμ‹ λ§Œμ˜ κ³ μœ ν•œ 값을 κ°€μ§ˆ 수 μžˆλ‹€.

μŠ€λ ˆλ“œ λ‘œμ»¬μ€ μŠ€ν”„λ§κ³Ό 같은 ν”„λ ˆμž„μ›Œν¬μ—μ„œ 많이 μ‚¬μš©λœλ‹€. λ©”μ†Œλ“œμ˜ λ§€κ°œλ³€μˆ˜λ‘œ μ „λ‹¬ν•˜μ§€ μ•Šκ³ λ„ 값에 accessκ°€ κ°€λŠ₯ν•˜λ‹€. μ•„λž˜μ™€ 같이 μ—¬λŸ¬ Serviceλ₯Ό κ±°μΉ˜λŠ” μš”μ²­μ΄ μžˆλ‹€.

  1. κ°€μž₯ λ¨Όμ € μš”μ²­μ΄ λ“€μ–΄μ˜€λ©΄ μ‚¬μš©μž 인증을 μ‹œλ„ν•œλ‹€.

    • 토큰이 생성될 수 있고, ν˜„μž¬ μŠ€λ ˆλ“œλŠ” μŠ€λ ˆλ“œ λ‘œμ»¬μ— 토큰과 μ‚¬μš©μž κΆŒν•œμ„ μ €μž₯ν•  수 μžˆλ‹€.

  2. λ§ˆμ§€λ§‰ μ„œλΉ„μŠ€ κ³„μΈ΅κΉŒμ§€ μ™”λ‹€. λ©”μ†Œλ“œκ°€ μ‹€ν–‰λ˜κΈ° 전에 κΆŒν•œμ„ ν™•μΈν•œλ‹€.

    • λͺ¨λ“  μ„œλΉ„μŠ€μ— μ‚¬μš©μž κΆŒν•œμ„ λ§€κ°œλ³€μˆ˜λ₯Ό 톡해 전달할 ν•„μš”λŠ” μ—†λ‹€.

      • μŠ€λ ˆλ“œλŠ” μŠ€λ ˆλ“œ λ‘œμ»¬μ— accessν•˜μ—¬ κΆŒν•œμ„ λ¬Όμ–΄λ³Ό 수 μžˆλ‹€.

    • 이것이 κ°€μž₯ 일반적인 사둀 쀑 ν•˜λ‚˜μ΄λ‹€.

λ©€ν‹°μ½”μ–΄ ν”„λ‘œμ„Έμ„œ μ‹œμŠ€ν…œμ—μ„œ Synchronizedλ₯Ό μ‚¬μš©ν•˜λ©΄ μŠ€λ ˆλ“œκ°€ Lock을 μ–»κΈ° μœ„ν•΄ λŒ€κΈ°ν•΄μ•Ό ν•œλ‹€.

μ΄λŠ” μ„±λŠ₯에 영ν–₯을 쀄 수 μžˆλ‹€.

λ”°λΌμ„œ 이 문제λ₯Ό ν•΄κ²°ν•˜κΈ° μœ„ν•΄μ„œλŠ” β€œμŠ€λ ˆλ“œ λ‘œμ»¬β€μ„ μ‚¬μš©ν•  수 μžˆλ‹€.

  • 각각의 μŠ€λ ˆλ“œλŠ” 객체λ₯Ό μƒμ„±ν•˜μ—¬ μŠ€λ ˆλ“œ λ‘œμ»¬μ— 넣을 수 μžˆλ‹€.

  • 동기화 및 μŠ€λ ˆλ“œ μ•ˆμ „μ„±μ— λŒ€ν•΄ κ±±μ •ν•  ν•„μš”κ°€ μ—†λ‹€.

ν•˜μ§€λ§Œ μŠ€λ ˆλ“œ λ‘œμ»¬μ—λ„ λͺ‡ κ°€μ§€ 결함이 μ‘΄μž¬ν•œλ‹€.

  • 변경이 κ°€λŠ₯ν•˜λ‹€.

  • GC에 μ˜ν•΄ μˆ˜κ±°λ˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ— 계속 λ©”λͺ¨λ¦¬μ— 남을 수 μžˆλ‹€.

    • μˆ˜λ™μœΌλ‘œ μ œκ±°ν•΄μ•Ό 함.

    • 이λ₯Ό μ œκ±°ν•˜λ €λ©΄ μŠ€λ ˆλ“œ μžμ²΄κ°€ μ£½κ±°λ‚˜ APIλ₯Ό 섀계해야 ν•œλ‹€.

    • 이것은 λ©”λͺ¨λ¦¬ λˆ„μˆ˜λ‘œ μ΄μ–΄μ§ˆ 수 μžˆλ‹€.

  • μŠ€λ ˆλ“œ λ‘œμ»¬μ€ 정적 파일과 ν•¨κ»˜ μ‚¬μš©λ˜μ–΄μ•Ό ν•œλ‹€. (static final)

  • removeλ₯Ό ν•˜λŠ”κ²ƒμ„ 잊으면 μ•ˆλœλ‹€.

    • μš”μ²­μ΄ 처리되면 κΌ­ 제거 ν•΄μ•Όν•œλ‹€. β†’ 이것이 μŠ€λ ˆλ“œ 둜컬의 ν•˜λ‚˜μ˜ 문제

μŠ€λ ˆλ“œ 둜컬의 μ£Όμš” νŠΉμ§•μ—λŠ” μŠ€λ ˆλ“œκ°€ μ’…λ£Œλ˜λ©΄ ν•΄λ‹Ή μŠ€λ ˆλ“œ 둜컬의 값도 μžλ™μœΌλ‘œ μ •λ¦¬λ˜λŠ”λ°, κ·Έλ ‡λ‹€λ©΄ remove ν•  ν•„μš”κ°€ μ—†λŠ”κ²ƒμ΄ μ•„λ‹Œκ°€?

μŠ€λ ˆλ“œ 객체가 더 이상 μ°Έμ‘°λ˜μ§€ μ•ŠμœΌλ©΄ ThreadLocal 값도 GC의 λŒ€μƒμ΄ λœλ‹€κ³  ν•œλ‹€.

μ—¬κΈ°μ„œ μ£Όμ˜ν•΄μ—¬ ν•  점은 μŠ€λ ˆλ“œ 풀을 μ‚¬μš©ν•˜λŠ” 경우인데, μŠ€λ ˆλ“œ ν’€μ—μ„œλŠ” μŠ€λ ˆλ“œκ°€ μ™„μ „νžˆ μ’…λ£Œλ˜μ§€ μ•Šκ³  μž¬μ‚¬μš©λ˜κΈ° λ•Œλ¬Έμ— ThreadLocal 값이 κ·ΈλŒ€λ‘œ λ‚¨μ•„μžˆμ„ 수 있기 λ•Œλ¬Έμ— μ΄λŸ¬ν•œ ν™˜κ²½μ΄λΌλ©΄ remove()의 μ‚¬μš©μ΄ ꢌμž₯λœλ‹€.

ν‚€ 쑰회 λ©”μ»€λ‹ˆμ¦˜

μ‹€μ œλ‘œ 같은 ThreadLocal의 객체λ₯Ό μ‚¬μš©ν•˜μ§€λ§Œ, 각 μŠ€λ ˆλ“œμ˜ κ³ μœ ν•œ 맡에 μ €μž₯λœλ‹€.

λ”°λΌμ„œ get()을 ν˜ΈμΆœν•˜λ©΄ ν˜„μž¬ μ‹€ν–‰ 쀑인 μŠ€λ ˆλ“œμ˜ λ§΅μ—μ„œ 값을 μ°ΎλŠ”λ‹€.

μŠ€λ ˆλ“œ 둜컬 상속

  1. μŠ€λ ˆλ“œ λ‘œμ»¬μ€ 상속될 수 μ—†λ‹€.

call 이 μ‹œμž‘λ  λ•Œ μƒˆλ‘œμš΄ μŠ€λ ˆλ“œλ₯Ό μƒμ„±ν•΄μ„œ λ©”μ†Œλ“œλ₯Ό ν˜ΈμΆœν•˜λŠ”λ°, token 값을 확인해보면 null이 λ“€μ–΄κ°€μžˆλ‹€.

  • ν•˜μœ„ μŠ€λ ˆλ“œκ°€ μƒμœ„ μŠ€λ ˆλ“œ 값에 access ν•  수 μ—†λ‹€.

λ§Œμ•½ μ ‘κ·Όν•˜κ³  μ‹Άλ‹€λ©΄ IngeritableThreadLocal<>()둜 μƒμ„±ν•œλ‹€.

  1. ν•˜μœ„ μŠ€λ ˆλ“œκ°€ λ‹€λ₯Έ 값을 μ„€μ •ν•˜λ©΄? μƒμœ„ μŠ€λ ˆλ“œκ°€ 영ν–₯을 λ°›μ„κΉŒ?

μƒμœ„ μŠ€λ ˆλ“œλŠ” 영ν–₯을 λ°›μ§€ μ•ŠλŠ”λ‹€. μƒˆλ‘œ λ³΅μ‚¬ν•˜κΈ° 떄문이닀.

  • ν•˜μœ„ μŠ€λ ˆλ“œμ—μ„œ 무언가λ₯Ό μˆ˜μ •ν•˜κ±°λ‚˜ μ œκ±°ν•˜λ©΄ λ°”λ€ŒκΈ΄ ν•˜μ§€λ§Œ ν•˜μœ„ μŠ€λ ˆλ“œμ—μ„œλ§Œ 영ν–₯을 μ€€λ‹€.

ν•˜λ‚˜μ˜ 가상 μŠ€λ ˆλ“œλŠ” 또 λ‹€λ₯Έ 가상 μŠ€λ ˆλ“œλ₯Ό 무수히 생성할 수 μžˆλ‹€.

이 κ³Όμ •μ—μ„œ ThreadLocal의 λͺ¨λ“  볡제, μ°Έμ‘° 볡제, ν•˜μœ„ μŠ€λ ˆλ“œμ™€μ˜ 곡유λ₯Ό 계속 μˆ˜ν–‰ν•œλ‹€λ©΄ λ¬Έμ œκ°€ λ°œμƒν•œλ‹€.

Scoped Value

  • comiler-plugin:21:β€”enable-previewλ₯Ό ν™œμ„±ν™” ν•΄μ•Όν•œλ‹€.

  • ν”„λ‘œλ•μ…˜ ν™˜κ²½μ—μ„œ μ‚¬μš©ν•˜λ©΄ μ•ˆλ¨

μŠ€λ ˆλ“œ λ‘œμ»¬μ—μ„œλŠ” 값이 μ—†λŠ”λ° get()을 ν•˜λ©΄ null을 λ°˜ν™˜ν•œλ‹€.

ν•˜μ§€λ§Œ μ—¬κΈ°μ„œλŠ” NoSuchElementException이 λ°œμƒν•œλ‹€. λ”°λΌμ„œ 값이 λ¨Όμ € μžˆλŠ”μ§€ 확인해야 ν•œλ‹€.

  • 값이 없더라도 orElseThrowλ₯Ό μ‚¬μš©ν•˜μ§€ 마라.

Last updated