Jumat dan akhir pekan lalu, saya beristirahat dari kesibukan saya dan meninjau implementasi Thread.interrupt dan LockSupport setelah Java 5 sambil menonton java cocurrent.
Sebelum memperkenalkan, izinkan saya mengajukan beberapa pertanyaan.
Apa hubungan antara metode Thread.interrupt() dan InterruptedException? Apakah pengecualian InterruptedException dipicu oleh interupsi?
Dalam keadaan apa Thread.interrupt() akan mengganggu pekerjaan thread? BERJALAN atau MEMBLOKIR?
Apakah pemrograman Thread secara umum perlu memperhatikan interupsi? Bagaimana cara mengatasinya secara umum? Untuk apa itu bisa digunakan?
Apa perbedaan antara LockSupport.park() dan unpark(), serta object.wait() dan notify()?
Apa gunanya objek pemblokir yang diteruskan oleh LockSupport.park(Pemblokir objek)?
Bisakah LockSupport merespons peristiwa Thread.interrupt()? Akankah InterruptedException dilempar?
Apakah ada fungsi panggilan balik yang sesuai untuk pemrosesan Thread.interrupt()? Sesuatu seperti panggilan kait?
Jika Anda bisa menjawab semuanya dengan jelas, berarti Anda sudah memahami sepenuhnya Thread.interrupt, dan Anda tidak perlu membaca lebih lanjut.
Jika Anda masih belum jelas, mari kita selesaikan bersama dengan pertanyaan-pertanyaan ini.
Beberapa metode untuk menangani interupsi Thread:
public void interupsi(): mengeksekusi acara interupsi thread
public boolean isInterrupted() : Periksa apakah thread saat ini terputus
boolean statis publik terputus(): Periksa apakah thread saat ini terputus dan setel ulang informasi interupsi. Mirip dengan resetAndGet()
memahami:
1. Setiap thread memiliki tanda status interupsi untuk menunjukkan apakah thread saat ini dalam keadaan terputus.
2. Secara umum, ada dua metode pemrosesan saat memanggil Thread.interrupt() ketika menghadapi status blok prioritas rendah, seperti object.wait(), object.sleep(), object.join(). Ini akan segera memicu pembukaan blokir untuk membuka blokir dan memunculkan InterruptedException.
Dalam kasus lain, Thread.interrupt() hanya memperbarui tanda status. Kemudian thread pekerja Anda memeriksa melalui Thread.isInterrrupted() dan dapat melakukan pemrosesan yang sesuai, seperti membuang InterruptedException atau menghapus status, membatalkan tugas, dll.
Dijelaskan dalam javadoc interupsi:
praktik terbaik
Ada artikel di IBM yang cukup bagus. Teori dan praktik Java: Berurusan dengan InterruptedException, yang menyebutkan beberapa praktik terbaik untuk penanganan Interupsi.
Jangan menelan interupsi (Jangan makan Interrupt, biasanya ada dua jenis pemrosesan: terus melempar InterruptedException. Yang lainnya adalah terus menyetel tanda pengecualian Thread.interupt(), sehingga level yang lebih tinggi dapat menanganinya sesuai dengan itu.
Copy kode kodenya sebagai berikut:
kelas publik TaskRunner mengimplementasikan Runnable {
antrian BlockingQueue<Tugas> pribadi;
public TaskRunner(antrian BlockingQueue<Tugas>) {
this.queue = antrian;
}
menjalankan kekosongan publik() {
mencoba {
sementara (benar) {
Tugas tugas = queue.take(10, TimeUnit.SECONDS);
tugas.eksekusi();
}
}
menangkap (InterruptedException e) {
// Memulihkan status yang terputus
Thread.currentThread().interrupt();
}
}
}
Copy kode kodenya sebagai berikut:
kelas publik TaskRunner mengimplementasikan Runnable {
antrian BlockingQueue<Tugas> pribadi;
public TaskRunner(antrian BlockingQueue<Tugas>) {
this.queue = antrian;
}
menjalankan kekosongan publik() {
mencoba {
sementara (benar) {
Tugas tugas = queue.take(10, TimeUnit.SECONDS);
tugas.eksekusi();
}
}
menangkap (InterruptedException e) {
// Memulihkan status yang terputus
Thread.currentThread().interrupt();
}
}
}
Menerapkan tugas yang dapat dibatalkan dengan Interrupt (gunakan Thread.interrupt() untuk merancang dan mendukung tugas yang dapat dibatalkan)
Copy kode kodenya sebagai berikut:
PrimeProducer kelas publik memperluas Thread {
antrian BlockingQueue<BigInteger> pribadi terakhir;
PrimeProducer(antrian BlockingQueue<BigInteger>) {
this.queue = antrian;
}
menjalankan kekosongan publik() {
mencoba {
Bilangan Bulat Besar p = Bilangan Bulat Besar.SATU;
while (!Thread.currentThread().isInterrupted())
antrian.put(p = p.nextProbablePrime());
} catch (InterruptedException digunakan) {
/* Izinkan thread keluar */
}
}
public void cancel() { interupsi() } // Memulai interupsi
<SPAN style="WHITE-SPACE: normal"> </SPAN>
Copy kode kodenya sebagai berikut:
PrimeProducer kelas publik memperluas Thread {
antrian BlockingQueue<BigInteger> pribadi terakhir;
PrimeProducer(antrian BlockingQueue<BigInteger>) {
this.queue = antrian;
}
menjalankan kekosongan publik() {
mencoba {
Bilangan Bulat Besar p = Bilangan Bulat Besar.SATU;
while (!Thread.currentThread().isInterrupted())
antrian.put(p = p.nextProbablePrime());
} catch (InterruptedException digunakan) {
/* Izinkan thread keluar */
}
}
public void cancel() { interupsi() } // Memulai interupsi
<SPAN style="WHITE-SPACE: normal"> </SPAN>
Daftarkan peristiwa pemrosesan Interupsi (penggunaan tidak normal)
Umumnya, tugas normal dirancang untuk menangani pembatalan, dan semuanya menggunakan polling aktif untuk memeriksa Thread.isInterrupt(), yang memiliki tingkat keterikatan tertentu dalam bisnis itu sendiri, dan ada juga penundaan pos pemeriksaan (siapa yang tahu kapan pos pemeriksaan berikutnya? Terutama saat melakukan socket.read, saya mengalami masalah batas waktu HttpClient).
Mari kita lihat. Implementasi pelemparan InterruptedException secara aktif didasarkan pada desain InterruptibleChannel yang cukup pintar.
Copy kode kodenya sebagai berikut:
interface InterruptAble {//Mendefinisikan antarmuka yang dapat diinterupsi
public void interupsi() melempar InterruptedException;
}
kelas abstrak InterruptSupport mengimplementasikan InterruptAble {
boolean volatil pribadi terputus = false;
interupsi interupsi pribadi = interupsi baru() {
interupsi kekosongan publik() {
terputus = benar;
InterruptSupport.ini.interrupt(); // Posisi 3
}
};
eksekusi boolean akhir publik() melempar InterruptedException {
mencoba {
diblokirPada(interupsi); // Posisi 1
if (Thread.currentThread().isInterrupted()) {// Segera diinterupsi
interuptor.interrupt();
}
//Jalankan kode bisnis
bisnis();
} Akhirnya {
diblokirPada(null); // Posisi 2
}
pengembalian terputus;
}
abstrak publik batal bisnis() ;
interupsi kekosongan abstrak publik();
// -- sun.misc.Rahasia Bersama --
static void diblokirOn(Interruptible intr) {// package-private
sun.misc.SharedSecrets.getJavaLangAccess().blockedOn(Thread.currentThread(), intr);
}
}
Copy kode kodenya sebagai berikut:
interface InterruptAble {//Mendefinisikan antarmuka yang dapat diinterupsi
public void interupsi() melempar InterruptedException;
}
kelas abstrak InterruptSupport mengimplementasikan InterruptAble {
boolean volatil pribadi terputus = false;
interupsi interupsi pribadi = interupsi baru() {
interupsi kekosongan publik() {
terputus = benar;
InterruptSupport.ini.interrupt(); // Posisi 3
}
};
eksekusi boolean akhir publik() melempar InterruptedException {
mencoba {
diblokirPada(interupsi); // Posisi 1
if (Thread.currentThread().isInterrupted()) {// Segera diinterupsi
interuptor.interrupt();
}
//Jalankan kode bisnis
bisnis();
} Akhirnya {
diblokirPada(null); // Posisi 2
}
pengembalian terputus;
}
abstrak publik batal bisnis() ;
interupsi kekosongan abstrak publik();
// -- sun.misc.Rahasia Bersama --
static void diblokirOn(Interruptible intr) {// package-private
sun.misc.SharedSecrets.getJavaLangAccess().blockedOn(Thread.currentThread(), intr);
}
}
Deskripsi kode, beberapa trik:
Posisi 1: Gunakan metode BlockOn yang disediakan oleh sun untuk mengikat kait pemrosesan peristiwa Interruptible yang sesuai ke Thread yang ditentukan.
Posisi 2: Setelah mengeksekusi kode, hapus hook. Hindari dampak pada peristiwa pemrosesan Thread berikutnya saat menggunakan kumpulan koneksi.
Posisi 3: Mendefinisikan metode pemrosesan dari event hook Interruptible dan memanggil kembali metode InterruptSupport.this.interrupt(). Subkelas dapat mengintegrasikan dan mengimplementasikan logika bisnisnya sendiri, seperti penutupan aliran kaus kaki, dll.
menggunakan:
Copy kode kodenya sebagai berikut:
kelas InterruptRead memperluas InterruptSupport {
FileInputStream pribadi di;
@Mengesampingkan
bisnis kekosongan publik() {
File file = new File("/dev/urandom"); // Membaca lubang hitam linux, tidak pernah selesai membaca
mencoba {
di = FileInputStream baru(file);
byte[] byte = byte baru[1024];
while (dalam.baca(byte, 0, 1024) > 0) {
// Thread.tidur(100);
// if (Thread.interrupted()) {// Metode pemeriksaan Interupsi Sebelumnya
// melempar InterruptedException baru("");
// }
}
} tangkapan (Pengecualian e) {
lempar RuntimeException baru(e);
}
}
FileInputStream publik getIn() {
kembali;
}
@Mengesampingkan
interupsi kekosongan publik() {
mencoba {
di.getChannel().close();
} tangkapan (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String args[]) memunculkan Pengecualian {
tes InterruptRead akhir = InterruptRead baru();
Utas t = Utas baru() {
@Mengesampingkan
menjalankan kekosongan publik() {
mulai panjang = System.currentTimeMillis();
mencoba {
System.out.println("InterruptRead mulai!");
tes.eksekusi();
} tangkapan (InterruptedException e) {
System.out.println("InterruptRead end! biaya waktu : " + (System.currentTimeMillis() - start));
e.printStackTrace();
}
}
};
t.mulai();
// Biarkan Read dijalankan selama 3 detik terlebih dahulu
Thread.tidur(3000);
//Keluarkan interupsi
t.interrupt();
}
Copy kode kodenya sebagai berikut:
kelas InterruptRead memperluas InterruptSupport {
FileInputStream pribadi di;
@Mengesampingkan
bisnis kekosongan publik() {
File file = new File("/dev/urandom"); // Membaca lubang hitam linux, tidak pernah selesai membaca
mencoba {
di = FileInputStream baru(file);
byte[] byte = byte baru[1024];
while (dalam.baca(byte, 0, 1024) > 0) {
// Thread.tidur(100);
// if (Thread.interrupted()) {// Metode pemeriksaan Interupsi Sebelumnya
// melempar InterruptedException baru("");
// }
}
} tangkapan (Pengecualian e) {
lempar RuntimeException baru(e);
}
}
FileInputStream publik getIn() {
kembali;
}
@Mengesampingkan
interupsi kekosongan publik() {
mencoba {
di.getChannel().close();
} tangkapan (IOException e) {
e.printStackTrace();
}
}
}
public static void main(String args[]) memunculkan Pengecualian {
tes InterruptRead akhir = InterruptRead baru();
Utas t = Utas baru() {
@Mengesampingkan
menjalankan kekosongan publik() {
mulai panjang = System.currentTimeMillis();
mencoba {
System.out.println("InterruptRead mulai!");
tes.eksekusi();
} tangkapan (InterruptedException e) {
System.out.println("InterruptRead end! biaya waktu : " + (System.currentTimeMillis() - start));
e.printStackTrace();
}
}
};
t.mulai();
// Biarkan Read dijalankan selama 3 detik terlebih dahulu
Thread.tidur(3000);
//Keluarkan interupsi
t.interrupt();
}
pengenalan kode sumber jdk:
1. Pengait yang disediakan oleh matahari dapat melihat kode Sistem yang relevan, baris: 1125
Copy kode kodenya sebagai berikut:
sun.misc.SharedSecrets.setJavaLangAccess(sun.misc.JavaLangAccess(){ baru
public sun.reflect.ConstantPool getConstantPool(Kelas kelas) {
kembalikan klass.getConstantPool();
}
public void setAnnotationType(Kelas kelas, tipe AnnotationType) {
klass.setAnnotationType(tipe);
}
public AnnotationType getAnnotationType(Kelas kelas) {
kembalikan klass.getAnnotationType();
}
publik <E memperluas Enum<E>>
E[] getEnumConstantsShared(Kelas<E> kelas) {
kembalikan klass.getEnumConstantsShared();
}
public void diblokirOn(Thread t, Interruptible b) {
t.blockedOn(b);
}
});
Copy kode kodenya sebagai berikut:
sun.misc.SharedSecrets.setJavaLangAccess(sun.misc.JavaLangAccess(){ baru
public sun.reflect.ConstantPool getConstantPool(Kelas kelas) {
kembalikan klass.getConstantPool();
}
public void setAnnotationType(Kelas kelas, tipe AnnotationType) {
klass.setAnnotationType(tipe);
}
public AnnotationType getAnnotationType(Kelas kelas) {
kembalikan klass.getAnnotationType();
}
publik <E memperluas Enum<E>>
E[] getEnumConstantsShared(Kelas<E> kelas) {
kembalikan klass.getEnumConstantsShared();
}
public void diblokirOn(Thread t, Interruptible b) {
t.blockedOn(b);
}
});
2. Utas.interupsi()
Copy kode kodenya sebagai berikut:
interupsi kekosongan publik() {
jika (ini!= Thread.currentThread())
periksaAkses();
disinkronkan (blockerLock) {
Dapat diinterupsi b = pemblokir;
jika (b != nol) {
interupsi0(); // Hanya untuk menyetel tanda interupsi
b.interrupt(); //kait panggilan balik
kembali;
}
}
interupsi0();
}
Copy kode kodenya sebagai berikut:
interupsi kekosongan publik() {
jika (ini!= Thread.currentThread())
periksaAkses();
disinkronkan (blockerLock) {
Dapat diinterupsi b = pemblokir;
jika (b != nol) {
interupsi0(); // Hanya untuk menyetel tanda interupsi
b.interrupt(); //kait panggilan balik
kembali;
}
}
interupsi0();
}
Untuk informasi lebih lanjut tentang penggunaan Thread.stop, suspend, resume, dan interupsi, Anda dapat melihat dokumentasi sun, seperti http://download.Oracle.com/javase/6/docs/technotes/guides/concurrency /threadPrimitiveDeprecation .html
Terakhir, mari kita jawab beberapa pertanyaan sebelumnya:
Pertanyaan 1: Apa hubungan antara metode Thread.interrupt() dan InterruptedException? Apakah pengecualian InterruptedException dipicu oleh interupsi?
Jawaban: Thread.interrupt() akan secara aktif menampilkan InterruptedException hanya di Object.wait(), .Object.join(), dan Object.sleep(). Hal ini biasa terjadi di blok lain, hanya dengan menyetel informasi flag Thread, dan program perlu memprosesnya sendiri.
Copy kode kodenya sebagai berikut:
if (Thread.interrupted()) // Menghapus status terputus!
melempar InterruptedException();
Copy kode kodenya sebagai berikut:
if (Thread.interrupted()) // Menghapus status terputus!
melempar InterruptedException();
Pertanyaan 2: Dalam keadaan apa Thread.interrupt() akan mengganggu pekerjaan thread? BERJALAN atau MEMBLOKIR?
Jawaban: Tujuan dari desain Thread.interrupt terutama untuk menangani thread dalam status blok, seperti status wait() dan sleep(). Namun, pembatalan tugas dapat didukung selama perancangan program, dan status RUNNING juga dapat didukung. Misalnya, Object.join() dan beberapa desain saluran nio yang mendukung interupsi.
Pertanyaan 3: Apakah pemrograman Thread secara umum perlu memperhatikan interupsi? Bagaimana cara mengatasinya secara umum? Untuk apa itu bisa digunakan?
Jawaban: Interupsi penggunaan: buka blokir operasi, mendukung pembatalan tugas, pembersihan data, dll.
Pertanyaan 4: Apa perbedaan antara LockSupport.park() dan unpark() dan object.wait() dan notify()?
menjawab:
1. Mata pelajarannya berbeda. LockSuport terutama melakukan pemrosesan pemblokiran untuk Thread. Ia dapat menentukan objek target antrian pemblokiran dan menentukan thread tertentu untuk diaktifkan setiap saat. Object.wait() mengambil objek sebagai dimensi, memblokir thread saat ini dan membangunkan satu (acak) atau semua thread.
2. Mekanisme pelaksanaannya berbeda. Meskipun LockSuport dapat menentukan objek objek monitor, antrian pemblokiran LockSuport dan object.wait() tidak berpotongan. Anda dapat melihat contoh tesnya. object.notifyAll() tidak dapat membangunkan Thread pemblokiran LockSupport.
Pertanyaan 5: Apa gunanya objek pemblokir yang diteruskan oleh LockSupport.park(Pemblokir objek)?
Jawaban: Blcoker yang sesuai akan dicatat dalam atribut parkBlocker dari Thread. Sangat mudah untuk memantau objek pemblokiran tertentu melalui perintah jstack.
Copy kode kodenya sebagai berikut:
public static void park(Pemblokir objek) {
Thread t = Thread.currentThread();
setBlocker(t, blocker); //Tetapkan nilai properti Thread.parkBlocker
tidak aman.park(false, 0L);
setBlocker(t, null); // Hapus nilai properti Thread.parkBlocker
}
Copy kode kodenya sebagai berikut:
public static void park(Pemblokir objek) {
Thread t = Thread.currentThread();
setBlocker(t, blocker); //Tetapkan nilai properti Thread.parkBlocker
tidak aman.park(false, 0L);
setBlocker(t, null); // Hapus nilai properti Thread.parkBlocker
}
Deskripsi spesifik javadoc dari LockSupport juga relatif jelas. Anda dapat membacanya di bawah:
Pertanyaan 6: Bisakah LockSupport merespons peristiwa Thread.interrupt()? Akankah InterruptedException dilempar?
Jawaban: Ia dapat merespons peristiwa interupsi, tetapi tidak akan memunculkan InterruptedException. Mengenai dukungan LockSupport untuk Thread.interrupte, lihat juga deskripsi di javadoc:
Kode pengujian terkait
Copy kode kodenya sebagai berikut:
paket com.agapple.cocurrent;
impor java.io.File;
impor java.io.FileInputStream;
import java.lang.reflect.Field;
import java.util.bersamaan.TimeUnit;
impor java.util.concurrent.locks.LockSupport;
Tes Dukungan Kunci kelas publik {
pemblokir LockSupportTest statis pribadi = lockSupportTest baru();
public static void main(String args[]) memunculkan Pengecualian {
lockSupportTest();
tes taman();
interupsiParkTest();
interupsiSleepTest();
interupsiWaitTest();
}
/**
* Setelah objek LockSupport.park, coba dapatkan objek Thread.blocker dan panggil bangun tunggalnya
*
* @throwsException
*/
private static void lockSupportTest() memunculkan Pengecualian {
Utas t = doTest(TesCallBack baru() {
@Mengesampingkan
public void callback() melempar Pengecualian {
// coba tidur 5 detik
System.out.println("pemblokir");
LockSupport.park(pemblokir);
System.out.println("Bangun sekarang!");
}
@Mengesampingkan
String publik getName() {
kembalikan "lockSupportTest";
}
});
t.start(); // Mulai membaca thread
Thread.tidur(150);
disinkronkan (pemblokir) {
Bidang bidang = Thread.class.getDeclaredField("parkBlocker");
field.setAccessible(benar);
Objek fBlocker = field.get(t);
System.out.println(pemblokir == fBlocker);
Thread.tidur(100);
System.out.println("notifyAll");
pemblokir.notifyAll();
}
}
/**
* Jika Anda mencoba menginterupsi suatu objek.wait(), InterruptedException yang sesuai akan dilempar.
*
* @melempar InterruptedException
*/
private static void interuptWaitTest() melempar InterruptedException {
objek akhir objek = Objek baru();
Utas t = doTest(TesCallBack baru() {
@Mengesampingkan
public void callback() melempar Pengecualian {
// coba tidur 5 detik
obj.tunggu();
System.out.println("Bangun sekarang!");
}
@Mengesampingkan
String publik getName() {
kembalikan "interruptWaitTest";
}
});
t.start(); // Mulai membaca thread
Thread.tidur(2000);
t.interrupt(); // Periksa apakah interupsi direspon selama parkir
}
/**
* Jika Anda mencoba mengganggu Thread.sleep(), InterruptedException yang sesuai akan dilempar.
*
* @melempar InterruptedException
*/
private static void interuptSleepTest() melempar InterruptedException {
Utas t = doTest(TesCallBack baru() {
@Mengesampingkan
public void callback() melempar Pengecualian {
// coba tidur 5 detik
Thread.tidur(5000);
System.out.println("Bangun sekarang!");
}
@Mengesampingkan
String publik getName() {
kembalikan "interruptSleepTest";
}
});
t.start(); // Mulai membaca thread
Thread.tidur(2000);
t.interrupt(); // Periksa apakah interupsi direspon selama parkir
}
/**
* Cobalah untuk menginterupsi LockSupport.park(), akan ada respons tetapi tidak ada pengecualian InterruptedException yang akan dilemparkan
*
* @melempar InterruptedException
*/
private static void interuppParkTest() melempar InterruptedException {
Utas t = doTest(TesCallBack baru() {
@Mengesampingkan
panggilan balik kekosongan publik() {
//Cobalah memarkir thread Anda sendiri
LockSupport.parkNanos(pemblokir, TimeUnit.SECONDS.toNanos(5));
System.out.println("Bangun sekarang!");
}
@Mengesampingkan
String publik getName() {
kembalikan "interruptParkTest";
}
});
t.start(); // Mulai membaca thread
Thread.tidur(2000);
t.interrupt(); // Periksa apakah interupsi direspon selama parkir
}
/**
* Cobalah untuk menginterupsi LockSupport.unPark(), akan ada respon
*
* @melempar InterruptedException
*/
private static void parkTest() melempar InterruptedException {
Utas t = doTest(TesCallBack baru() {
@Mengesampingkan
panggilan balik kekosongan publik() {
//Cobalah memarkir thread Anda sendiri
LockSupport.park(pemblokir);
System.out.println("Bangun sekarang!");
}
@Mengesampingkan
String publik getName() {
kembalikan "parkTest";
}
});
t.start(); // Mulai membaca thread
Thread.tidur(2000);
LockSupport.unpark(t);
t.interrupt();
}
public static Thread doTest(panggilan TestCallBack terakhir) {
kembalikan Thread baru() {
@Mengesampingkan
menjalankan kekosongan publik() {
File file = File baru("/dev/urandom"); // Baca lubang hitam linux
mencoba {
FileInputStream di = FileInputStream baru(file);
byte[] byte = byte baru[1024];
while (dalam.baca(byte, 0, 1024) > 0) {
if (Utas.interrupted()) {
melempar InterruptedException baru("");
}
System.out.println(byte[0]);
Thread.tidur(100);
mulai panjang = System.currentTimeMillis();
panggilan.panggilan balik();
System.out.println(call.getName() + " biaya penyelesaian panggilan balik : "
+ (System.currentTimeMillis() - mulai));
}
} tangkapan (Pengecualian e) {
e.printStackTrace();
}
}
};
}
}
antarmuka TestCallBack {
public void callback() melempar Pengecualian;
String publik getName();
}
Copy kode kodenya sebagai berikut:
paket com.agapple.cocurrent;
impor java.io.File;
impor java.io.FileInputStream;
import java.lang.reflect.Field;
import java.util.bersamaan.TimeUnit;
impor java.util.concurrent.locks.LockSupport;
Tes Dukungan Kunci kelas publik {
pemblokir LockSupportTest statis pribadi = lockSupportTest baru();
public static void main(String args[]) memunculkan Pengecualian {
lockSupportTest();
tes taman();
interupsiParkTest();
interupsiSleepTest();
interupsiWaitTest();
}
/**
* Setelah objek LockSupport.park, coba dapatkan objek Thread.blocker dan panggil bangun tunggalnya
*
* @throwsException
*/
private static void lockSupportTest() memunculkan Pengecualian {
Utas t = doTest(TesCallBack baru() {
@Mengesampingkan
public void callback() melempar Pengecualian {
// coba tidur 5 detik
System.out.println("pemblokir");
LockSupport.park(pemblokir);
System.out.println("Bangun sekarang!");
}
@Mengesampingkan
String publik getName() {
kembalikan "lockSupportTest";
}
});
t.start(); // Mulai membaca thread
Thread.tidur(150);
disinkronkan (pemblokir) {
Bidang bidang = Thread.class.getDeclaredField("parkBlocker");
field.setAccessible(benar);
Objek fBlocker = field.get(t);
System.out.println(pemblokir == fBlocker);
Thread.tidur(100);
System.out.println("notifyAll");
pemblokir.notifyAll();
}
}
/**
* Jika Anda mencoba menginterupsi suatu objek.wait(), InterruptedException yang sesuai akan dilempar.
*
* @melempar InterruptedException
*/
private static void interuptWaitTest() melempar InterruptedException {
objek akhir objek = Objek baru();
Utas t = doTest(TesCallBack baru() {
@Mengesampingkan
public void callback() melempar Pengecualian {
// coba tidur 5 detik
obj.tunggu();
System.out.println("Bangun sekarang!");
}
@Mengesampingkan
String publik getName() {
kembalikan "interruptWaitTest";
}
});
t.start(); // Mulai membaca thread
Thread.tidur(2000);
t.interrupt(); // Periksa apakah interupsi direspon selama parkir
}
/**
* Jika Anda mencoba mengganggu Thread.sleep(), InterruptedException yang sesuai akan dilempar.
*
* @melempar InterruptedException
*/
private static void interuptSleepTest() melempar InterruptedException {
Utas t = doTest(TesCallBack baru() {
@Mengesampingkan
public void callback() melempar Pengecualian {
// coba tidur 5 detik
Thread.tidur(5000);
System.out.println("Bangun sekarang!");
}
@Mengesampingkan
String publik getName() {
kembalikan "interruptSleepTest";
}
});
t.start(); // Mulai membaca thread
Thread.tidur(2000);
t.interrupt(); // Periksa apakah interupsi direspon selama parkir
}
/**
* Cobalah untuk menginterupsi LockSupport.park(), akan ada respons tetapi tidak ada pengecualian InterruptedException yang akan dilemparkan
*
* @melempar InterruptedException
*/
private static void interuppParkTest() melempar InterruptedException {
Utas t = doTest(TesCallBack baru() {
@Mengesampingkan
panggilan balik kekosongan publik() {
//Cobalah memarkir thread Anda sendiri
LockSupport.parkNanos(pemblokir, TimeUnit.SECONDS.toNanos(5));
System.out.println("Bangun sekarang!");
}
@Mengesampingkan
String publik getName() {
kembalikan "interruptParkTest";
}
});
t.start(); // Mulai membaca thread
Thread.tidur(2000);
t.interrupt(); // Periksa apakah interupsi direspon selama parkir
}
/**
* Cobalah untuk menginterupsi LockSupport.unPark(), akan ada respon
*
* @melempar InterruptedException
*/
private static void parkTest() melempar InterruptedException {
Utas t = doTest(TesCallBack baru() {
@Mengesampingkan
panggilan balik kekosongan publik() {
//Cobalah memarkir thread Anda sendiri
LockSupport.park(pemblokir);
System.out.println("Bangun sekarang!");
}
@Mengesampingkan
String publik getName() {
kembalikan "parkTest";
}
});
t.start(); // Mulai membaca thread
Thread.tidur(2000);
LockSupport.unpark(t);
t.interrupt();
}
public static Thread doTest(panggilan TestCallBack terakhir) {
kembalikan Thread baru() {
@Mengesampingkan
menjalankan kekosongan publik() {
File file = File baru("/dev/urandom"); // Baca lubang hitam linux
mencoba {
FileInputStream di = FileInputStream baru(file);
byte[] byte = byte baru[1024];
while (dalam.baca(byte, 0, 1024) > 0) {
if (Utas.interrupted()) {
melempar InterruptedException baru("");
}
System.out.println(byte[0]);
Thread.tidur(100);
mulai panjang = System.currentTimeMillis();
panggilan.panggilan balik();
System.out.println(call.getName() + " biaya penyelesaian panggilan balik : "
+ (System.currentTimeMillis() - mulai));
}
} tangkapan (Pengecualian e) {
e.printStackTrace();
}
}
};
}
}
antarmuka TestCallBack {
public void callback() melempar Pengecualian;
String publik getName();
}
Akhirnya <BR>Saya menemukan bahwa artikel tersebut semakin panjang, jadi saya cukup mempostingnya di forum agar semua orang dapat berdiskusi bersama. Lagi pula, artikel tersebut hanya menjelaskan beberapa hal tingkat penggunaan, dan tidak memperkenalkan Thread dari pengoperasian implementasi sistem atau sun native. Untuk beberapa mekanisme, Daniumen yang akrab dengan bidang ini juga dapat mengutarakan pendapatnya.