Rumah  >  Artikel  >  Java  >  Cara menggunakan kelas java.lang.ThreadLocal

Cara menggunakan kelas java.lang.ThreadLocal

PHPz
PHPzke hadapan
2023-05-05 20:43:13701semak imbas

1. Gambaran Keseluruhan

Apakah ThreadLocal? Sebenarnya, ThreadLocal bukanlah versi pelaksanaan setempat bagi suatu utas Ia bukan suatu Thread, tetapi pembolehubah setempat (thread local variable). Mungkin lebih sesuai untuk menamakannya ThreadLocalVar. Fungsi sebenar pembolehubah setempat utas (ThreadLocal) adalah sangat mudah Ia adalah untuk menyediakan salinan nilai pembolehubah untuk setiap utas yang menggunakan pembolehubah Ia adalah mekanisme pengikatan utas khas di Jawa yang membolehkan setiap utas secara bebas Mengubah sendiri salin tanpa bercanggah dengan salinan benang lain.

Dari perspektif utas, setiap utas mengekalkan rujukan tersirat kepada salinan pembolehubah setempat utas asalkan utas itu aktif dan tika ThreadLocal boleh diakses selepas utas itu hilang, semua salinan tika utas setempatnya akan menjadi Sampah koleksi (melainkan terdapat rujukan lain kepada salinan ini).

Data yang diakses melalui ThreadLocal sentiasa berkaitan dengan urutan semasa Dalam erti kata lain, JVM mengikat ruang akses contoh tempatan peribadi kepada setiap utas yang sedang berjalan, dengan itu menyediakan penyelesaian untuk masalah akses serentak yang sering berlaku dalam persekitaran berbilang benang .

Bagaimanakah ThreadLocal mengekalkan salinan pembolehubah untuk setiap utas? Sebenarnya, idea pelaksanaannya sangat mudah Terdapat Peta dalam kelas ThreadLocal untuk menyimpan salinan pembolehubah setiap utas.

Kesimpulannya, untuk masalah perkongsian sumber berbilang benang, mekanisme penyegerakan menggunakan kaedah "bertukar masa untuk ruang", manakala ThreadLocal menggunakan kaedah "bertukar ruang untuk masa". Yang pertama hanya menyediakan salinan pembolehubah untuk utas yang berbeza untuk beratur untuk akses, manakala yang terakhir menyediakan salinan pembolehubah untuk setiap utas, supaya ia boleh diakses pada masa yang sama tanpa menjejaskan satu sama lain.

2. Penerangan API

ThreadLocal()

Buat pembolehubah setempat benang.

T dapat()

Mengembalikan nilai dalam salinan benang semasa bagi pembolehubah setempat benang ini, yang dibuat dan dimulakan jika ini adalah kali pertama utas memanggil kaedah ini.

dilindungi T initialValue()

Mengembalikan nilai awal benang semasa untuk pembolehubah setempat benang ini. Kaedah ini dipanggil paling banyak sekali setiap capaian benang untuk mendapatkan setiap pembolehubah setempat-benang, iaitu, apabila utas mula-mula mengakses pembolehubah menggunakan kaedah get(). Jika utas memanggil kaedah set(T) sebelum kaedah get, kaedah initialValue tidak akan dipanggil semula dalam utas.

Jika pelaksanaan ini hanya mengembalikan null jika pengaturcara ingin memulakan pembolehubah thread-local kepada nilai selain daripada null, pengaturcara mesti subkelas ThreadLocal dan mengatasi kaedah ini. Biasanya, kelas dalaman tanpa nama akan digunakan. Pelaksanaan biasa initialValue akan memanggil pembina yang sesuai dan mengembalikan objek yang baru dibina.

void remove()

Mengalih keluar nilai pembolehubah setempat benang ini. Ini boleh membantu mengurangkan keperluan storan untuk pembolehubah setempat benang. Jika pembolehubah setempat-benang ini diakses semula, ia akan mempunyai nilai permulaannya secara lalai.

set lompang(nilai T)

Menetapkan nilai dalam salinan benang semasa pembolehubah setempat benang ini kepada nilai yang ditentukan. Banyak aplikasi tidak memerlukan fungsi ini dan hanya bergantung pada kaedah initialValue() untuk menetapkan nilai pembolehubah setempat-benang.

Dalam atur cara, kaedah nilai permulaan biasanya ditindih untuk memberikan nilai permulaan tertentu.

3. Contoh biasa

1. Kelas alat Sesi Hiberante HibernateUtil

Kelas ini ialah kelas HibernateUtil dalam dokumentasi rasmi Hibernate dan digunakan untuk pengurusan sesi.

kelas awam HibernateUtil {

log Log statik peribadi = LogFactory.getLog(HibernateUtil.class);

private static final SessionFactory sessionFactory; //Define SessionFactory

statik {

cuba {

//Buat SessionFactory

melalui fail konfigurasi lalai hibernate.cfg.xml sessionFactory = new Configuration().configure().buildSessionFactory();

} tangkapan (Bekas boleh baling) {

log.error("Inisialisasi SessionFactory gagal!", ex);

buang ExceptionIninitalizerError(ex);

baharu }

}

//Buat sesi pembolehubah setempat benang untuk menyimpan Sesi Hibernate

sesi ThreadLocal akhir statik awam = ThreadLocal baharu();

/**

* Dapatkan Sesi

dalam urutan semasa * Sesi @kembali

* @membuang HibernateException

*/

public static Session currentSession() membuang HibernateException {

Sesi s = (Sesi) session.get();

// Jika Sesi belum dibuka, buka Sesi baharu

jika (s == batal) {

s = sessionFactory.openSession();

session.set(s); //Simpan Sesi yang baru dibuka ke dalam pembolehubah setempat utas

}

kembali s;

}

public static void closeSession() membuang HibernateException {

//Dapatkan pembolehubah tempatan urutan dan hantar ke jenis Sesi

Sesi s = (Sesi) session.get();

session.set(null);

jika (s != null)

s.close();

}

}

Dalam kelas ini, memandangkan kaedah initialValue() ThreadLocal tidak ditindih, sesi pembolehubah tempatan utas dibuat buat kali pertama dan nilai awalnya adalah nol Apabila currentSession() dipanggil buat kali pertama, kaedah get(). daripada pembolehubah tempatan benang juga nol. Oleh itu, sesi dinilai Jika ia adalah batal, Sesi baharu dibuka dan disimpan dalam sesi pembolehubah tempatan utas Ini juga merupakan objek yang dibuat oleh "sesi ThreadLocal akhir statik awam = new ThreadLocal(). " Sebab mengapa sesi boleh dipaksa menjadi objek Sesi Hibernate.

2. Contoh lain

Buat Bean dan tetapkan sifat Bean melalui objek benang yang berbeza untuk memastikan kebebasan setiap objek Bean benang.

/**

* Dicipta oleh IntelliJ IDEA.

* Pengguna: leizhimin

* Tarikh: 2007-11-23

* Masa: 10:45:02

* 学生

*/

Pelajar kelas awam {

umur int peribadi = 0; //Umur

public int getAge() {

kembalikan umur ini;

}

public void setAge(int age) {

this.age = umur;

}

}

/**

* Dicipta oleh IntelliJ IDEA.

* Pengguna: leizhimin

* Tarikh: 2007-11-23

* Masa: 10:53:33

* Program ujian di bawah multi-threading

*/

kelas awam ThreadLocalDemo melaksanakan Runnable {

//Buat utas pembolehubah setempat studentLocal Kemudian anda akan mendapati ia digunakan untuk menyimpan objek Pelajar

peribadi akhir statik ThreadLocal studentLocal = new ThreadLocal();

public static void main(String[] agrs) {

ThreadLocalDemo td = ThreadLocalDemo();

Thread t1 = Thread baharu(td, "a");

Thread t2 = Thread baharu(td, "b");

t1.start();

t2.start();

}

public void run() {

accessStudent();

}

/**

* Contoh kaedah perniagaan untuk ujian

*/

public void accessPelajar() {

//Dapatkan nama urutan semasa

String currentThreadName = Thread.currentThread().getName();

System.out.println(currentThreadName + " sedang berjalan!");

//Jana nombor rawak dan cetak

Rawak rawak = new Random();

umur int = rawak.nextInt(100);

System.out.println("thread " + currentThreadName + " tetapkan umur kepada:" + umur);

//Dapatkan objek Pelajar dan masukkan umur rawak ke dalam sifat objek

Pelajar pelajar = getStudent();

pelajar.setUmur(umur);

System.out.println("thread " + currentThreadName + " umur baca pertama ialah:" + student.getAge());

cuba {

Thread.sleep(500);

}

tangkap (exception InterruptedException) {

ex.printStackTrace();

}

System.out.println("thread " + currentThreadName + " umur baca kedua ialah:" + student.getAge());

}

dilindungi Pelajar getStudent() {

//Dapatkan pembolehubah urutan tempatan dan hantar ke jenis Pelajar

Pelajar pelajar = (Pelajar) studentLocal.get();

//Apabila urutan melaksanakan kaedah ini buat kali pertama, studentLocal.get() mestilah batal

jika (pelajar == batal) {

//Buat objek Pelajar dan simpan pada pembolehubah utas setempat studentLocal

pelajar = Pelajar baharu();

studentLocal.set(pelajar);

}

pelajar kembali;

}

}

Keputusan berjalan:

a sedang berjalan!

masukkan umur yang ditetapkan kepada:76

b sedang berjalan!

benang b tetapkan umur kepada:27

urutan umur bacaan pertama ialah:76

thread b pertama membaca umur ialah:27

urutan umur bacaan kedua ialah:76

thread b umur bacaan kedua ialah:27

Ia dapat dilihat bahawa nilai yang dicetak oleh umur dua benang pada masa yang berbeza adalah sama. Program ini menggunakan ThreadLocal untuk mencapai konkurensi berbilang benang sambil mengambil kira keselamatan data.

4. Ringkasan

ThreadLocal digunakan terutamanya untuk menyelesaikan masalah ketidakkonsistenan data akibat keselarasan dalam berbilang benang. ThreadLocal menyediakan salinan data yang diakses serentak dalam setiap utas, dan menjalankan perniagaan dengan mengakses salinan Ini menggunakan memori, sangat mengurangkan penggunaan prestasi yang disebabkan oleh penyegerakan utas, dan juga mengurangkan kerumitan kawalan serentak utas.

ThreadLocal tidak boleh menggunakan jenis atom, hanya jenis Objek. Penggunaan ThreadLocal adalah lebih mudah daripada disegerakkan.

Kedua-dua ThreadLocal dan Synchonized digunakan untuk menyelesaikan akses serentak berbilang benang. Tetapi terdapat perbezaan penting antara ThreadLocal dan disegerakkan. Disegerakkan menggunakan mekanisme kunci supaya pembolehubah atau blok kod hanya boleh diakses oleh satu utas pada satu masa. ThreadLocal menyediakan salinan pembolehubah untuk setiap utas, supaya setiap utas tidak mengakses objek yang sama pada masa tertentu, sekali gus mengasingkan perkongsian data data oleh berbilang utas. Disegerakkan adalah sebaliknya. Ia digunakan untuk mendapatkan perkongsian data apabila berkomunikasi antara berbilang benang.

Disegerakkan digunakan untuk perkongsian data antara utas, manakala ThreadLocal digunakan untuk pengasingan data antara utas.

Sudah tentu, ThreadLocal tidak boleh menggantikan disegerakkan, mereka berurusan dengan domain masalah yang berbeza. Disegerakkan digunakan untuk melaksanakan mekanisme penyegerakan dan lebih kompleks daripada ThreadLocal.

5. Langkah am untuk menggunakan ThreadLocal

1. Dalam kelas berbilang benang (seperti kelas ThreadDemo), cipta objek ThreadLocal threadXxx untuk menyimpan objek xxx yang perlu diasingkan antara benang.

2. Dalam kelas ThreadDemo, cipta kaedah getXxx() untuk mendapatkan data untuk diakses secara berasingan Hakim dalam kaedah bahawa jika objek ThreadLocal adalah batal, anda harus new() objek jenis akses pengasingan dan memaksanya. untuk diaplikasikan.

3. Dalam kaedah run() kelas ThreadDemo, dapatkan data untuk dikendalikan melalui kaedah getXxx() Ini memastikan setiap utas sepadan dengan objek data dan objek ini dikendalikan pada bila-bila masa.

Atas ialah kandungan terperinci Cara menggunakan kelas java.lang.ThreadLocal. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:yisu.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam