tgoop.com/javapro_ir/4682
Last Update:
📘 آشنایی عمیق با ThreadLocalMap و نحوهٔ واقعی ذخیرهسازی دادهها در ThreadLocal
در ادامهٔ آموزش قبلی دربارهٔ ThreadLocal، اکنون لازم است ساختار داخلی آن در JVM را بررسی کنیم. فهمیدن سازوکار ThreadLocalMap باعث میشود دقیقاً بدانیم دادهها چگونه ذخیره میشوند، چرا Memory Leak ممکن است رخ بدهد، و چرا remove() اهمیت حیاتی دارد.
✳️ ۱. ThreadLocal چگونه دادهها را ذخیره میکند؟
در ظاهر، برنامهنویس فقط با کلاس ThreadLocal کار میکند.
اما در پشت صحنه:
هر Thread یک شیء مستقل بهنام ThreadLocalMap دارد.
این ساختار داخل کلاس Thread قرار دارد و متعلق به همان Thread است.
بنابراین دادهها نه در خود ThreadLocal، بلکه در ThreadLocalMap مربوط به هر Thread ذخیره میشوند.
ساختار کلی به این شکل است:
* هر Thread یک ThreadLocalMap دارد
* هر ThreadLocalMap شامل چند Entry است
* هر Entry دارای یک کلید از جنس WeakReference<ThreadLocal> و یک مقدار (Object) است
با این طراحی، هر Thread نسخهٔ خصوصی دادههای خودش را دارد.
✳️ ۲. کلیدهای ThreadLocalMap از نوع WeakReference هستند
در داخل ThreadLocalMap، کلید اصلی هر مقدار، یک WeakReference به شیء ThreadLocal است.
دلیل این طراحی:
* اگر برنامهنویس ThreadLocal را فراموش کند از بین ببرد
* JVM بتواند ThreadLocal را Garbage Collect کند
* اما مقدار ذخیرهشده در Map هنوز باقی میماند
این نکته منجر به موضوع مهم بعدی میشود.
✳️ ۳. چرا Memory Leak ممکن است رخ بدهد؟
وقتی ThreadLocal بهصورت WeakReference نگه داشته میشود، ممکن است ThreadLocal از بین برود، اما مقدارش در ThreadLocalMap باقی بماند.
این وضعیت زمانی خطرناک میشود که:
* Thread مربوطه در ThreadPool باشد
* Thread پس از پایان کار از بین نرود
* مقدار ذخیرهشده همچنان در ThreadLocalMap باقی بماند
در این صورت، دادهٔ قبلی غیرقابل دسترس اما غیرقابل حذف خواهد بود و باعث Memory Leak میشود.
برای جلوگیری از این مشکل بهترین کار همیشه استفاده از:
threadLocal.remove();
در بلوک finally است.
✳️ ۴. مثال: شبیهسازی رفتار ThreadLocalMap
در مثال زیر نشان میدهیم چطور ThreadLocalMap در هر Thread دادههای مختلف نگه میدارد:
public class ThreadLocalMapDemo {
private static ThreadLocal<String> threadLocal = new ThreadLocal<>();
public static void main(String[] args) {
Runnable task = () -> {
threadLocal.set("Value for " + Thread.currentThread().getName());
System.out.println(Thread.currentThread().getName() + ": " + threadLocal.get());
threadLocal.remove();
};
new Thread(task, "Thread-A").start();
new Thread(task, "Thread-B").start();
}
}
در اینجا برای هر Thread مقدار جداگانهای در ThreadLocalMap ذخیره شده و پس از remove دیگر هیچ دادهای باقی نمیماند.
✳️ ۵. جمعبندی ساختار داخلی ThreadLocal
درک ThreadLocalMap کمک میکند بدانیم ThreadLocal چگونه واقعاً کار میکند:
* هر Thread یک ThreadLocalMap مخصوص خود دارد.
* کلیدها WeakReference به شیء ThreadLocal هستند.
* مقدارها Strong Reference هستند و اگر remove نشوند ممکن است در حافظه گیر کنند.
* استفاده از remove برای جلوگیری از Memory Leak ضروری است، بهخصوص در ThreadPoolها.
* طراحی ThreadLocalMap باعث میشود دادههای Thread-Specific بهصورت امن و جداگانه مدیریت شوند.
#کاربرـحرفهـای
🆔 @javapro_ir
🆔 @group_javapro
BY جاواپرو | برنامه نویسی جاوا | Java
Share with your friend now:
tgoop.com/javapro_ir/4682
