Kelas ThreadLocal dapat dipahami sebagai ThreadLocalVariable (variabel lokal thread), yang menyediakan antarmuka akses atau metode seperti get dan set. Metode ini menyimpan salinan independen untuk setiap thread yang menggunakan variabel, sehingga get selalu mengembalikan lokasi eksekusi saat ini thread. Nilai terbaru yang ditetapkan saat memanggil set. ThreadLocal<T> dapat dianggap berisi objek Map<Thread,T>, yang menyimpan nilai khusus untuk thread tersebut.
Singkatnya, untuk masalah berbagi sumber daya multi-thread, mekanisme sinkronisasi mengadopsi metode "menukar waktu dengan ruang", sedangkan ThreadLocal mengadopsi metode "menukar ruang dengan waktu". Yang pertama hanya menyediakan salinan variabel untuk thread yang berbeda untuk mengantri akses, sedangkan yang kedua menyediakan salinan variabel untuk setiap thread, sehingga dapat diakses pada saat yang sama tanpa mempengaruhi satu sama lain.
Thread MockLokal
Copy kode kodenya sebagai berikut:
impor java.util.Koleksi;
impor java.util.HashMap;
import java.util.Map;
kelas publik SimpleThreadLocal<T> {
peta pribadi<Utas, T> valueMap = Koleksi
.synchronizedMap(HashMap baru<Thread, T>());
kumpulan kekosongan publik(T Nilai baru) {
valueMap.put(Thread.currentThread(), newValue); // ①Kuncinya adalah objek thread dan nilainya adalah salinan variabel thread ini
}
publik T dapatkan() {
Thread currentThread = Thread.currentThread();
T o = valueMap.get(currentThread); // ② Mengembalikan variabel yang sesuai dengan thread ini
if (o == null && !valueMap.containsKey(currentThread)) { // ③Jika tidak ada di Peta, masukkan ke dalam Peta dan simpan.
o = Nilai awal();
valueMap.put(Thread saat ini, o);
}
kembali o;
}
kekosongan publik hapus() {
valueMap.remove(Thread.currentThread());
}
dilindungi T nilai awal() {
kembalikan nol;
}
}
UtilitasThreadLokal
Copy kode kodenya sebagai berikut:
Jumlah kelas {
private SimpleThreadLocal<Integer> count = new SimpleThreadLocal<Integer>() {
@Mengesampingkan
Nilai awal Integer yang dilindungi() {
kembali 0;
}
};
peningkatan bilangan bulat publik() {
hitungan.set(hitungan.get() + 1);
kembalikan hitungan.get();
}
}
kelas TestThread mengimplementasikan Runnable {
hitungan pribadi;
TestThread publik(Hitungan hitungan) {
this.count = hitungan;
}
@Mengesampingkan
menjalankan kekosongan publik() {
// TODO Stub metode yang dibuat secara otomatis
untuk (int saya = 1; saya <= 3; saya++) {
Sistem.keluar.println(Thread.currentThread().getName() + "/t" + i
+ "th/t" + hitungan.peningkatan());
}
}
}
kelas publik TestThreadLocal {
public static void main(String[] args) {
Hitungan hitungan = Hitungan baru();
Thread t1 = Thread baru(Thread Test baru(hitungan));
Thread t2 = Thread baru(Thread Test baru(hitungan));
Thread t3 = Thread baru(Thread Test baru(hitungan));
Thread t4 = Thread baru(Thread Test baru(hitungan));
t1.mulai();
t2.mulai();
t3.mulai();
t4.mulai();
}
}
Kode salinan keluarannya adalah sebagai berikut:
Utas-0 1 1
Utas-0 2 2
Utas-0 3 3
Utas-3 1 1
Utas-1 1 1
Utas-1 2 2
Utas-2 1 1
Utas-1 3 3
Utas-3 2 2
Utas-3 3 3
Utas-2 2 2
Utas-2 3 3