CodeGym /Java Blog /Acak /Multithreading: Apa yang dilakukan metode kelas Thread
John Squirrels
Level 41
San Francisco

Multithreading: Apa yang dilakukan metode kelas Thread

Dipublikasikan di grup Acak
Hai! Hari ini kita akan terus berbicara tentang multithreading. Mari kita periksa kelas Thread dan apa yang dilakukan beberapa metodenya. Ketika kami mempelajari metode kelas sebelumnya, kami biasanya hanya menulis ini: <nama metode> -> <apa yang dilakukan metode>. Multithreading: Apa yang dilakukan metode kelas Thread - 1Ini tidak akan bekerja dengan Threadmetode :) Mereka memiliki logika yang lebih kompleks sehingga Anda tidak akan dapat mengetahuinya tanpa beberapa contoh.

Metode Thread.start()

Mari kita mulai dengan mengulangi diri kita sendiri. Seperti yang mungkin Anda ingat, Anda dapat membuat utas dengan membuat kelas Anda mewarisi kelas Threaddan mengganti run()metodenya. Tapi itu tidak akan mulai sendiri, tentu saja. Untuk melakukan ini, kita memanggil metode objek kita start(). Multithreading: Apa yang dilakukan metode kelas Thread - 2Mari kita ingat contoh dari pelajaran sebelumnya:

public class MyFirstThread extends Thread {

   @Override
   public void run() {
       System.out.println("Thread executed: " + getName());
   }
}


public class Main {

   public static void main(String[] args) {

       for (int i = 0; i < 10; i++) {
           MyFirstThread thread = new MyFirstThread();
           thread.start();
       }
   }
}
Catatan: Untuk memulai utas, Anda harus memanggilstart()metode khusus daripadarun()metode! Ini adalah kesalahan yang mudah dilakukan, terutama saat Anda pertama kali mempelajari multithreading. Dalam contoh kami, jika Anda memanggilrun()metode 10 kali alih-alihstart(), Anda akan mendapatkan ini:

public class Main {

   public static void main(String[] args) {

       for (int i = 0; i < 10; i++) {
           MyFirstThread thread = new MyFirstThread();
           thread.run();
       }
   }
}
Lihat hasil program kita: Thread dieksekusi: Thread-0 Thread dieksekusi: Thread-1 Thread dieksekusi: Thread-2 Thread dieksekusi: Thread-3 Thread dieksekusi: Thread-4 Thread dieksekusi: Thread-5 Thread dieksekusi: Thread-6 Utas dieksekusi: Utas-7 Utas dieksekusi: Utas-8 Utas dieksekusi: Utas-9 Lihat urutan keluaran: Semuanya terjadi dalam urutan yang sempurna. Aneh, ya? Kami tidak terbiasa dengan ini, karena kami sudah tahu bahwa urutan thread dimulai dan dieksekusi ditentukan oleh kecerdasan superior di dalam sistem operasi kami: thread scheduler. Mungkin kita hanya beruntung? Tentu saja, ini bukan tentang keberuntungan. Anda dapat memverifikasi ini dengan menjalankan program beberapa kali lagi. Masalahnya adalah panggilan iturun()metode langsung tidak ada hubungannya dengan multithreading. Dalam hal ini, program akan dijalankan pada utas utama, utas yang sama yang menjalankan metode main(). Itu hanya mencetak 10 baris berturut-turut pada konsol dan hanya itu. 10 utas belum dimulai. Jadi, ingatlah ini di masa depan dan terus periksa diri Anda. Jika Anda ingin run()metode dipanggil, panggil start(). Mari melangkah lebih jauh.

Metode Thread.sleep()

Untuk menangguhkan eksekusi utas saat ini untuk sementara waktu, kami menggunakan sleep()metode ini. Multithreading: Apa yang dilakukan metode kelas Thread - 3Metode ini sleep()membutuhkan beberapa milidetik sebagai argumen, yang menunjukkan jumlah waktu untuk menidurkan utas.

public class Main {

   public static void main(String[] args) throws InterruptedException {

       long start = System.currentTimeMillis();

       Thread.sleep(3000);

       System.out.println(" - How long did I sleep? \n - " + ((System.currentTimeMillis()-start)) / 1000 + " seconds");

   }
}
Keluaran konsol: - Berapa lama saya tidur? - 3 detik Catatan: metode sleep()ini statis: ia menidurkan utas saat ini. Artinya, yang saat ini sedang dieksekusi. Inilah poin penting lainnya: utas tidur dapat terputus. Dalam hal ini, program melempar file InterruptedException. Kami akan mempertimbangkan contoh di bawah ini. Omong-omong, apa yang terjadi setelah utas bangun? Apakah itu akan terus dieksekusi langsung dari tempat yang ditinggalkannya? Tidak. Setelah utas bangun, yaitu waktu yang berlalu sebagai argumen telah Thread.sleep()berlalu, utas akan bertransisi menjadi dapat dijalankannegara. Namun, ini tidak berarti penjadwal utas akan menjalankannya. Ini mungkin memberikan preferensi ke beberapa utas non-tidur lainnya dan memungkinkan utas kami yang baru terbangun untuk melanjutkan pekerjaannya nanti. Pastikan untuk mengingat ini: bangun tidak berarti langsung melanjutkan pekerjaan!

Metode Thread.join()

Multithreading: Apa yang dilakukan metode kelas Thread - 4Metode join()menangguhkan eksekusi utas saat ini hingga utas lainnya selesai. Jika kita memiliki 2 utas, t1dan t2, dan kita menulis

t1.join()
maka t2tidak akan mulai sampai t1selesai pekerjaannya. Metode ini join()dapat digunakan untuk menjamin urutan eksekusi utas. Mari pertimbangkan cara join()kerja metode ini dalam contoh berikut:

public class ThreadExample extends Thread {

   @Override
   public void run() {

       System.out.println("Thread started: " + getName());

       try {
           Thread.sleep(5000);
       } catch (InterruptedException e) {
           e.printStackTrace();
       }
       System.out.println("Thread " + getName() + " is finished.");
   }
}


public class Main {

   public static void main(String[] args) throws InterruptedException {

       ThreadExample t1 = new ThreadExample();
       ThreadExample t2 = new ThreadExample();

       t1.start();


 /* The second thread (t2) will start running only after the first thread (t1)
       is finished (or an exception is thrown) */
       try {
           t1.join();
       } catch (InterruptedException e) {
           e.printStackTrace();
       }

       t2.start();

       // The main thread will continue running only after t1 and t2 have finished
       try {
           t1.join();
           t2.join();
       } catch (InterruptedException e) {
           e.printStackTrace();
       }

       System.out.println("All threads have finished. The program is finished.");

   }
}
Kami membuat kelas sederhana ThreadExample. Tugasnya adalah menampilkan pesan bahwa utas telah dimulai, tertidur selama 5 detik, dan akhirnya melaporkan bahwa pekerjaan telah selesai. Sepotong kue. Logika utama ada di Mainkelas. Lihat komentarnya: kami menggunakan join()metode untuk berhasil mengelola urutan eksekusi utas. Jika Anda ingat bagaimana kita memulai topik ini, urutan eksekusi ditangani oleh penjadwal utas. Ini menjalankan utas atas kebijaksanaannya sendiri: setiap kali dengan cara yang berbeda. Di sini kami menggunakan metode untuk menjamin bahwa t1utas akan dimulai dan dieksekusi terlebih dahulu, kemudiant2utas, dan hanya setelah itu utas utama program akan dilanjutkan. Bergerak. Dalam program nyata, Anda akan sering menemukan situasi ketika Anda perlu menghentikan eksekusi utas. Misalnya, thread kita sedang berjalan, tetapi sedang menunggu event atau kondisi tertentu. Jika itu terjadi, maka utas berhenti. Mungkin masuk akal jika ada semacam stop()metode. Tapi itu tidak begitu sederhana. Sekali waktu, Java sebenarnya memiliki Thread.stop()metode dan membiarkan utas diinterupsi. Tapi kemudian dihapus dari perpustakaan Java. Anda dapat menemukannya di dokumentasi Oracle dan melihat bahwa itu ditandai sebagai usang. Mengapa? Karena itu hanya menghentikan utas tanpa melakukan hal lain. Misalnya, utas mungkin bekerja dengan data dan mengubah sesuatu. Kemudian di tengah pekerjaannya itu dipotong secara tiba-tiba dan begitu saja dengan stop()metode tersebut. Tanpa shutdown yang tepat, atau pelepasan sumber daya, bahkan penanganan kesalahan - tidak ada semua ini. Untuk sedikit melebih-lebihkan, stop()metode ini menghancurkan segalanya dengan caranya sendiri. Rasanya seperti mencabut kabel listrik dari stopkontak untuk mematikan komputer. Ya, Anda bisa mendapatkan hasil yang diinginkan. Tetapi semua orang tahu bahwa setelah beberapa minggu komputer tidak akan berterima kasih kepada Anda karena telah memperlakukannya seperti itu. Itu sebabnya logika untuk menyela utas berubah di Jawa dan sekarang menggunakan interrupt()metode khusus.

Metode Thread.interrupt()

Apa yang terjadi jika interrupt()metode ini dipanggil di utas? Ada 2 kemungkinan:
  1. Jika objek berada dalam keadaan menunggu, misalnya karena metode joinatau sleep, maka penantian akan dihentikan dan program akan melontarkan InterruptedException.
  2. Jika utas dalam keadaan berfungsi, maka interruptedbendera boolean akan disetel pada objek.
Tapi kita harus memeriksa nilai flag ini pada objek dan menyelesaikan pekerjaan kita sendiri dengan benar! Itu sebabnya Threadkelas memiliki boolean isInterrupted()metode. Mari kembali ke contoh jam yang ada di pelajaran di kursus dasar. Untuk kenyamanan, kami telah sedikit menyederhanakannya:

public class Clock extends Thread {

   public static void main(String[] args) throws InterruptedException {
       Clock clock = new Clock();
       clock.start();

       Thread.sleep(10000);
       clock.interrupt();
   }

   public void run() {
       Thread current = Thread.currentThread();

       while (!current.isInterrupted())
       {
           try {
               Thread.sleep(1000);
           } catch (InterruptedException e) {
               System.out.println("The thread was interrupted");
               break;
           }
           System.out.println("Tick");
       }
   }
}
Dalam hal ini, jam dimulai dan mulai berdetak setiap detik. Pada detik ke-10, kami menghentikan utas jam. Seperti yang sudah Anda ketahui, jika utas yang kami coba interupsi berada di salah satu status menunggu, hasilnya adalah InterruptedException. Ini adalah pengecualian yang dicentang, sehingga kita dapat dengan mudah menangkapnya dan menjalankan logika kita untuk menyelesaikan program. Dan itulah yang kami lakukan. Inilah hasil kami: Tick Tick Tick Tcik Tick Tick Tick Tick Tick Utas terputus Ini mengakhiri pengenalan kita pada Threadmetode kelas yang paling penting. Semoga beruntung!
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION