يمكن فهم فئة ThreadLocal على أنها ThreadLocalVariable (متغير مؤشر الترابط المحلي)، والذي يوفر واجهات أو طرق وصول مثل get وset. تخزن هذه الطرق نسخة مستقلة لكل مؤشر ترابط يستخدم المتغير، لذا تُرجع get دائمًا موقع التنفيذ الحالي thread. أحدث قيمة تم تعيينها عند استدعاء set. يمكن اعتبار ThreadLocal<T> أنه يحتوي على كائن Map<Thread,T> ويحمل قيمًا خاصة بهذا الخيط.
خلاصة القول، بالنسبة لمشكلة مشاركة الموارد متعددة الخيوط، تعتمد آلية المزامنة طريقة "تبادل الوقت بالمكان"، بينما يعتمد ThreadLocal أسلوب "تبادل المكان بالوقت". يوفر الأول فقط نسخة من المتغير لسلاسل رسائل مختلفة في قائمة الانتظار للوصول، بينما يوفر الأخير نسخة من المتغير لكل مؤشر ترابط، بحيث يمكن الوصول إليها في نفس الوقت دون التأثير على بعضها البعض.
موضوع وهمية محلي
انسخ رمز الكود كما يلي:
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
فئة عامة SimpleThreadLocal<T> {
خريطة خاصة <Thread, T> valueMap = Collections
.synchronizedMap(new HashMap<Thread, T>());
مجموعة الفراغ العامة (T newValue) {
valueMap.put(Thread.currentThread(), newValue); // ①المفتاح هو كائن الخيط والقيمة هي نسخة من متغير هذا الخيط
}
الحصول على T العام () {
الموضوع الحاليThread = Thread.currentThread();
T o = valueMap.get(currentThread); // ② قم بإرجاع المتغير المقابل لهذا الموضوع
if (o == null && !valueMap.containsKey(currentThread)) { // ③إذا لم يكن موجودًا في الخريطة، فضعه في الخريطة واحفظه.
س = القيمة الأولية ()؛
valueMap.put(currentThread, o);
}
العودة س؛
}
إزالة الفراغ العام () {
valueMap.remove(Thread.currentThread());
}
محمية T القيمة الأولية () {
عودة فارغة؛
}
}
الأداة المساعدةThreadLocal
انسخ رمز الكود كما يلي:
عدد الفصول {
الخاص SimpleThreadLocal<Integer> count = new SimpleThreadLocal<Integer>() {
@تجاوز
عدد صحيح محمي القيمة الأولية () {
العودة 0؛
}
};
زيادة عدد صحيح عام () {
count.set(count.get() + 1);
إرجاع العد.get();
}
}
فئة TestThread تنفذ Runnable {
عدد العد الخاص؛
موضوع الاختبار العام (عدد العد) {
this.count = count;
}
@تجاوز
تشغيل الفراغ العام () {
// TODO طريقة تم إنشاؤها تلقائيًا stub
لـ (int i = 1; i <= 3; i++) {
System.out.println(Thread.currentThread().getName() + "/t" + i
+ "th/t" + count.increase());
}
}
}
الطبقة العامة TestThreadLocal {
public static void main(String[] args) {
عدد العد = عدد جديد ()؛
Thread t1 = new Thread(new TestThread(count));
Thread t2 = new Thread(new TestThread(count));
Thread t3 = new Thread(new TestThread(count));
Thread t4 = new Thread(new TestThread(count));
t1.start();
t2.start();
t3.start();
t4.start();
}
}
رمز نسخة الإخراج كما يلي:
الموضوع-0 1 1
الموضوع-0 2 2
الموضوع-0 3 3
الموضوع-3 1
الموضوع-1 1 1
الموضوع-1 2 2
الموضوع-2 1 1
الموضوع-1 3 3
الموضوع-3 2
الموضوع-3 3
الموضوع-2 2
الموضوع-2 3 3