Mulai utas:
1. Deskripsi perbedaan antara start () dan run ()
start (): fungsinya adalah untuk memulai utas baru, dan utas baru akan menjalankan metode run () yang sesuai. start () tidak dapat dipanggil berulang kali.
run (): run () dapat disebut berulang kali seperti metode anggota biasa. Jika Anda menelepon run () secara terpisah, run () akan dieksekusi di utas saat ini, dan utas baru tidak akan dimulai!
Berikut ini adalah kode untuk dijelaskan.
kelas mythread memperluas utas {public void run () {...}}; mythread mythread = new mythread (); myThread.start () memulai utas baru dan menjalankan metode run () di utas baru.
MyThread.run () akan menjalankan metode run () langsung di utas saat ini, dan tidak akan memulai utas baru untuk menjalankan run ().
2. Contoh perbedaan antara start () dan run ()
Di bawah ini, tunjukkan perbedaan di antara mereka dengan contoh sederhana. Kode sumber adalah sebagai berikut:
// kelas kode sumber demo.java MyThread memperluas utas {public mythread (nama string) {super (name); } public void run () {System.out.println (thread.currentThread (). getName ()+"sedang berjalan"); }}; Demo kelas publik {public static void main (string [] args) {thread mythread = new mythread ("mythread"); System.out.println (thread.currentThread (). GetName ()+"hubungi mythread.run ()"); mythread.run (); System.out.println (thread.currentThread (). GetName ()+"Call MyThread.Start ()"); mythread.start (); }} Hasil Menjalankan:
panggilan utama mythread.run () Main runningmain call mythread.start () mythread sedang berjalan
Deskripsi Hasil:
(1) thread.currentThread (). GetName () digunakan untuk mendapatkan nama "utas saat ini". Utas saat ini mengacu pada utas yang dijadwalkan untuk dieksekusi di CPU.
(2) mythread.run () disebut dalam "utas utama utama", dan metode run () berjalan langsung pada "utas utama utama".
(3) mythread.start () akan mulai "Thread MyThread". Setelah "Thread MyThread" dimulai, metode run () akan dipanggil; Pada saat ini metode run () dijalankan pada "Thread MyThread".
Interupsi dan penghentian utas
1. Thread Interrupt: Interrupt ()
Fungsi interrupt () adalah untuk mengganggu utas.
Utas ini diizinkan untuk mengganggu dirinya sendiri; Ketika utas lain memanggil metode interrupt () dari utas ini, izin akan diperiksa melalui checkAccess (). Ini mungkin melempar pengecualian Exception keamanan.
Jika utas dalam keadaan pemblokiran: panggilan tunggu (), tunggu (panjang) atau tunggu (panjang, int) utas akan membuatnya menjadi status menunggu (memblokir), atau memanggil gabungan (), bergabung (panjang), bergabung (panjang, int), tidur (panjang), tidur (panjang, int) dari utas juga akan masuk ke keadaan pemblokiran. Jika utas memanggil metode interuprik () saat memblokir, "status interupsi" akan dibersihkan dan ExcepedException akan diterima. Misalnya, utas memasuki keadaan pemblokiran melalui tunggu (), dan utas tersebut terganggu oleh interrupt (); Calling Interrupt () akan segera mengatur bendera interupsi utas ke "Benar", tetapi karena utasnya dalam keadaan pemblokiran, "bendera interupsi" akan segera dibersihkan menjadi "false", dan Excepted Exception akan dihasilkan.
Jika utas diblokir dalam pemilih pemilih, maka ketika terganggu oleh interrupt (); Bendera interupsi utas diatur ke true dan akan segera dikembalikan dari operasi seleksi.
Jika bukan milik situasi yang disebutkan di atas, maka ketika utas terganggu melalui interupsi (), bendera interupsi akan diatur ke "benar".
Mengganggu "utas yang diakhiri" tidak akan menyebabkan operasi apa pun.
2. Pengakhiran Thread
Metode stop () dan suspend () dalam utas disarankan untuk tidak digunakan karena rasa tidak aman yang melekat!
Selanjutnya, pertama -tama saya akan membahas metode penghentian utas dalam "status pemblokiran" dan "keadaan menjalankan" masing -masing, dan kemudian merangkum metode umum.
1. Menghentikan utas dalam "status pemblokiran"
Biasanya, kami menghentikan utas dalam "status pemblokiran" dengan "mengganggu".
Ketika utas memasuki keadaan pemblokiran karena disebut sleep (), tunggu (), gabungkan () dan metode lainnya; Jika interupsi () dari utas dipanggil pada saat ini, tanda interupsi utas diatur ke true. Karena dalam keadaan pemblokiran, bendera interupsi akan dibersihkan dan pengecualian Exception interrupted dihasilkan. Menempatkan interruptedException sampai sesuai dapat mengakhiri utas, dalam bentuk sebagai berikut:
@Overridepublic void run () {coba {while (true) {// Jalankan tugas ...}} catch (interruptedException yaitu) {// karena pengecualian ExtraySception, keluar dari loop while (true) dan utas diakhiri! }} Catatan: Ketika tugas terus dieksekusi dalam sementara (benar), ketika utas dalam keadaan pemblokiran, panggilan untuk mengganggu () dari utas menghasilkan interupsi interupsi interupsi. Penangkapan yang terputus ada di luar sementara (benar), sehingga keluar dari loop sementara (benar)!
Catatan: Penangkapan ExcepedException biasanya ditempatkan di luar badan loop sementara (benar), sehingga loop sementara (benar) keluar ketika pengecualian dihasilkan. Kalau tidak, jika interruptedException berada di dalam badan loop sementara (benar), diperlukan penambahan tambahan dan keluar dari pemrosesan. Bentuknya adalah sebagai berikut:
@OverridEpublic void run () {while (true) {coba {// Jalankan tugas ...} catch (InterruptedException IE) {// InterruptedException ada di badan loop sementara (true). // Ketika utas menghasilkan pengecualian ExcepedException, sementara (benar) dapat terus berjalan! Perlu keluar secara manual; }}} CATATAN: Pengecualian Exception di atas ditangkap dalam whle (benar). Ketika pengecualian Exception interupsi dihasilkan, itu tidak ditangani oleh tangkapan dan masih dalam tubuh loop sementara (benar); Untuk keluar dari badan loop sementara (benar), operasi tambahan keluar dari sementara (benar) perlu dilakukan.
2. Akhiri utas dalam "status menjalankan"
Biasanya, kami mengakhiri utas dalam "keadaan berjalan" dengan "Marking". Di antara mereka, itu termasuk "bendera interupsi" dan "tambahkan bendera tambahan".
(1) Akhiri utas melalui "bendera interupsi".
Bentuknya adalah sebagai berikut:
@OverridEpublic void run () {while (! IsInterrupted ()) {// Jalankan tugas ...}} Deskripsi: isInterrupted () menentukan apakah bendera interupsi utas benar. Saat utas dalam keadaan menjalankan dan kita perlu menghentikannya; Metode interrupt () utas dapat dipanggil, dan bendera interupsi utas ditandai benar, yaitu, terputus () akan mengembalikan true. Pada titik ini, loop sementara akan keluar.
Catatan: interrupt () tidak mengakhiri utas dalam "status berjalan"! Ini mengatur bendera interupsi utas ke True.
(2) lulus "Tambahkan tanda tambahan".
Bentuknya adalah sebagai berikut:
Private Volatile Boolean Flag = true; void stopTask yang dilindungi () {flag = false;}@overrididepublic void run () {while (flag) {// Jalankan tugas ...}} Deskripsi: Ada tag flag di utas, dan nilai defaultnya benar; Dan kami menyediakan stopTask () untuk mengatur tag bendera. Ketika kita perlu mengakhiri utas, memanggil metode stopTask () dari utas dapat menyebabkan utas keluar dari loop sementara.
Catatan: Bendera didefinisikan sebagai tipe volatil untuk memastikan visibilitas bendera. Artinya, setelah utas lain memodifikasi flag melalui stopTask (), utas ini dapat melihat nilai bendera yang dimodifikasi.
Komprehensif Metode penghentian utas dalam "status pemblokiran" dan "keadaan berjalan", utas penghentian yang lebih umum adalah sebagai berikut:
@Overridepublic void run () {coba {// 1. IsInterrupted () menjamin bahwa utas akan diakhiri selama interupsi ditandai benar. while (! isInterrupted ()) {// Jalankan tugas ...}} catch (InterruptedException IE) {// 2. Pengecualian ExtrectedException menjamin bahwa ketika pengecualian Exception InterruptedException terjadi, utas diakhiri. }} 3. Contoh Terminasi Thread
Interrupt () sering digunakan untuk mengakhiri utas "status pemblokiran". Lihat contoh berikut:
// Demo1.java's Source Code Class MyThread Extends Thread {public mythread (nama string) {super (name); } @Override public void run () {coba {int i = 0; while (! isInterrupted ()) {thread.sleep (100); // tidur 100ms i ++; System.out.println (thread.currentThread (). GetName ()+"("+this.getState ()+") loop"+i); }} catch (InterruptedException e) {System.out.println (thread.currentThread (). getName ()+"("+this.getState ()+") Catch InterruptException."); }}} kelas publik demo1 {public static void main (string [] args) {coba {thread t1 = myThread baru ("t1"); // Buat "Thread T1" baru "System.out.println (t1.getName ()+" ("+t1.getState ()+") adalah baru. "); t1.start (); // Mulai "Thread T1" System.out.println (t1.getName ()+"("+t1.getState ()+") dimulai."); // Benang utama tidur selama 300 ms, dan kemudian utas utama mengirimkan instruksi "interupsi" ke T1. Thread.sleep (300); t1.interrupt (); System.out.println (t1.getName ()+"("+t1.getState ()+") terganggu."); // Benang utama tidur selama 300 ms, lalu memeriksa status T1. Thread.sleep (300); System.out.println (t1.getName ()+"("+t1.getState ()+") terganggu sekarang."); } catch (InterruptedException e) {E.PrintStackTrace (); }}} Hasil Menjalankan:
T1 (baru) adalah new.t1 (runnable) dimulai.t1 (runnable) loop 1t1 (runnable) loop 2t1 (timed_waiting) terganggu.t1 (runnable) Catch InterruptException.t1 (Terakhir) terganggu sekarang.
Deskripsi Hasil:
(1) Utas utama utama membuat utas T1 melalui mythread baru ("T1"), dan kemudian memulai utas T1 melalui t1.start ().
(2) Setelah T1 dimulai, bendera interupsi akan diperiksa terus menerus. Jika bendera interupsi "salah", itu akan tidur selama 100ms.
(3) Setelah T1 tidur, itu akan beralih ke utas utama; Ketika utas utama berjalan lagi, t1.interrupt () akan dieksekusi untuk mengganggu utas T1. Setelah T1 menerima instruksi interupsi, bendera interupsi T1 akan diatur ke "false" dan ExcepedException akan dilemparkan. Dalam metode run () T1, ini adalah pengecualian yang ditangkap di luar badan loop sementara; Oleh karena itu loop diakhiri.
Kami membuat modifikasi kecil untuk hasil di atas dan memindahkan blok kode yang menangkap pengecualian Exception interrupted dalam metode run () ke badan loop sementara.
// Demo2.java's Source Code Class MyThread Extends Thread {public mythread (name string) {super (name); } @Override public void run () {int i = 0; while (! isInterrupted ()) {coba {thread.sleep (100); // tidur untuk 100ms} catch (interruptedException IE) {System.out.println (thread.currentThread (). GetName ()+"("+this.getState ()+") Catch InterruptException."); } i ++; System.out.println (thread.currentThread (). GetName ()+"("+this.getState ()+") loop"+i); }}} kelas publik demo2 {public static void main (string [] args) {coba {thread t1 = myThread baru ("t1"); // Buat "Thread T1" baru "System.out.println (t1.getName ()+" ("+t1.getState ()+") adalah baru. "); t1.start (); // Mulai "Thread T1" System.out.println (t1.getName ()+"("+t1.getState ()+") dimulai."); // Benang utama tidur selama 300 ms, dan kemudian utas utama mengirimkan instruksi "interupsi" ke T1. Thread.sleep (300); t1.interrupt (); System.out.println (t1.getName ()+"("+t1.getState ()+") terganggu."); // Benang utama tidur selama 300 ms, lalu memeriksa status T1. Thread.sleep (300); System.out.println (t1.getName ()+"("+t1.getState ()+") terganggu sekarang."); } catch (InterruptedException e) {E.PrintStackTrace (); }}} Hasil Menjalankan:
t1 (NEW) is new.t1 (RUNNABLE) is started.t1 (RUNNABLE) loop 1t1 (RUNNABLE) loop 2t1 (TIMED_WAITING) is interrupted.t1 (RUNNABLE) catch InterruptedException.t1 (RUNNABLE) loop 3t1 (RUNNABLE) loop 4t1 (RUNNABLE) loop 5t1 (TIMED_WAITING) is interrupted now.t1 (Runnable) loop 6t1 (runnable) loop 7t1 (runnable) loop 8t1 (runnable) loop 9 ...
Deskripsi Hasil:
Program ini telah memasuki loop dead!
Mengapa ini terjadi? Ini karena T1 terganggu oleh interrupt () ketika itu "menunggu (memblokir) status". Pada saat ini, bendera interupsi dibersihkan [yang terputus () akan mengembalikan false], dan pengecualian Exception interrupted dilemparkan [pengecualian ini terperangkap dalam badan loop while]. Oleh karena itu, T1 secara alami akan memasuki lingkaran setan.
Untuk mengatasi masalah ini, kita perlu pemrosesan ekstra untuk keluar dari loop saat menangkap pengecualian. Misalnya, menambahkan istirahat atau kembali ke Mythread Catch (InterruptedException) dapat menyelesaikan masalah.
Berikut adalah contoh utas yang mengakhiri "status status" dengan "menambahkan tag tambahan":
// Demo33.Java's Source Code Class MyThread Extends Thread {Private Volatile Boolean Flag = True; public void stopTask () {flag = false; } public mythread (nama string) {super (name); } @Override public void run () {disinkronkan (ini) {coba {int i = 0; while (flag) {thread.sleep (100); // tidur 100ms i ++; System.out.println (thread.currentThread (). GetName ()+"("+this.getState ()+") loop"+i); }} catch (InterruptedException IE) {System.out.println (thread.currentThread (). getName ()+"("+this.getState ()+") Catch InterruptedException."); }}}} kelas publik demo3 {public static void main (string [] args) {coba {mythread t1 = mythread baru ("t1"); // Buat "Thread T1" System.out.println (t1.getName ())+"baru ("+t1.getState ()+") adalah baru."); t1.start (); // Mulai "Thread T1" System.out.println (t1.getName ()+"("+t1.getState ()+") dimulai."); // Benang utama tidur selama 300 ms, dan kemudian utas utama mengirimkan instruksi "interupsi" ke T1. Thread.sleep (300); t1.stoptask (); System.out.println (t1.getName ()+"("+t1.getState ()+") terganggu."); // Benang utama tidur selama 300 ms, lalu memeriksa status T1. Thread.sleep (300); System.out.println (t1.getName ()+"("+t1.getState ()+") terganggu sekarang."); } catch (InterruptedException e) {E.PrintStackTrace (); }}} Hasil Menjalankan:
T1 (baru) adalah new.t1 (runnable) dimulai.t1 (runnable) loop 1t1 (runnable) loop 2t1 (timed_waiting) terganggu.t1 (runnable) loop 3T1 (diakhiri) terganggu sekarang.