Halo! Hari ini kita terus berbicara tentang multithreading. Mari kita lihat kelas Thread dan cara kerja beberapa metodenya. Sebelumnya, ketika kita mempelajari metode kelas, kita paling sering menulisnya seperti ini: “nama metode” -> “apa fungsinya”.
Ini tidak akan berfungsi dengan metode Thread :) Logikanya lebih rumit, dan tanpa beberapa contoh mustahil untuk memahaminya.
itu akan menjadi bahan tambahan yang bagus! Pada bagian akhir, setelah ikhtisar metode, akan dijelaskan apa yang akan kita lalui selanjutnya dalam kursus ini :) Semoga berhasil!
Metode Thread.start()
Mari kita mulai dengan pengulangan. Seperti yang mungkin Anda ingat, Anda dapat membuat thread dengan mewarisi kelas Anda dari kelas tersebutThread
dan mengganti metode di dalamnya run()
. Namun, tentu saja, hal ini tidak akan dimulai dengan sendirinya. Untuk melakukan ini, kita memanggil metode pada objek kita start()
. Mari kita ingat contoh kuliah sebelumnya:
public class MyFirstThread extends Thread {
@Override
public void run() {
System.out.println("Выполнен поток " + getName());
}
}
public class Main {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
MyFirstThread thread = new MyFirstThread();
thread.start();
}
}
}
Harap diperhatikan: untuk memulai thread, Anda harus memanggil metode khususstart()
, bukanrun()
! Ini adalah kesalahan yang mudah dilakukan, terutama saat pertama kali mempelajari multithreading. Jika dalam contoh kita Anda memanggil metode pada suatu objek sebanyak 10 kalirun()
bukanstart()
, hasilnya akan seperti ini:
public class Main {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
MyFirstThread thread = new MyFirstThread();
thread.run();
}
}
}
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 thread dieksekusi Thread-7 thread dieksekusi Thread-8 thread dieksekusi Thread-9 thread dieksekusi Lihatlah urutan keluarannya: semuanya berjalan teratur. Aneh, bukan? Kami tidak terbiasa dengan hal ini, karena kami sudah mengetahui bahwa urutan peluncuran dan eksekusi thread ditentukan oleh kecerdasan super di dalam sistem operasi kami - penjadwal thread. Mungkin aku hanya beruntung? Tentu saja ini bukan soal keberuntungan. Anda dapat memverifikasi ini dengan menjalankan program beberapa kali lagi. Intinya memanggil suatu metode secara langsungrun()
tidak ada hubungannya dengan multithreading. Dalam hal ini, program akan dieksekusi di thread utama - thread tempat metode dijalankanmain()
. Ini hanya akan menampilkan 10 baris secara berurutan ke konsol dan hanya itu. Tidak ada 10 thread yang akan dimulai. Oleh karena itu, ingatlah untuk masa depan dan selalu periksa diri Anda. Jika Anda ingin hal itu dilakukanrun()
, teleponlahstart()
. Mari kita lanjutkan.
Metode Thread.sleep()
Untuk menghentikan sementara eksekusi thread saat ini selama beberapa waktu, gunakan ekstensisleep()
. Metode ini sleep()
mengambil parameter jumlah milidetik, yaitu waktu yang diperlukan thread untuk dialihkan ke mode tidur.
public class Main {
public static void main(String[] args) throws InterruptedException {
long start = System.currentTimeMillis();
Thread.sleep(3000);
System.out.println(" - Сколько я проспал? \n - " + ((System.currentTimeMillis()-start)) / 1000 + " секунды");
}
}
Keluaran konsol: - Berapa lama saya tidur? - 3 detik Harap dicatat: metode sleep()
ini statis: ini membuat thread saat ini tertidur. Artinya, salah satu yang sedang bekerja saat ini. Nuansa penting lainnya: aliran dalam kondisi tidur bisa terganggu. Dalam hal ini, pengecualian akan terjadi pada program InterruptedException
. Kita akan melihat contohnya di bawah ini. Ngomong-ngomong, apa yang terjadi setelah thread “bangun”? Akankah ia segera melanjutkan eksekusinya dari titik terakhirnya? TIDAK. Setelah thread aktif—ketika waktu yang berlalu sebagai argumen berakhir Thread.sleep()
— thread memasuki status runnable . Namun, ini tidak berarti penjadwal thread akan menjalankannya. Sangat mungkin bahwa ia akan memberikan preferensi pada beberapa utas "tidak tidur" lainnya, dan utas "yang baru dibangunkan" kami akan terus bekerja beberapa saat kemudian. Pastikan untuk mengingat: “bangun bukan berarti terus bekerja saat itu juga!”
Metode Thread.join()
Metode inijoin()
menangguhkan eksekusi thread saat ini hingga thread lain selesai. Jika kita mempunyai 2 thread, t1
dan t2
, dan kita menulis -
t1.join()
t2
tidak akan mulai bekerja sampai t1 menyelesaikan pekerjaannya. Metode ini join()
dapat digunakan untuk memastikan urutan eksekusi thread. Mari kita lihat pekerjaannya join()
menggunakan sebuah contoh:
public class ThreadExample extends Thread {
@Override
public void run() {
System.out.println("Начало работы потока " + getName());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Поток " + getName() + " завершил работу.");
}
}
public class Main {
public static void main(String[] args) throws InterruptedException {
ThreadExample t1 = new ThreadExample();
ThreadExample t2 = new ThreadExample();
t1.start();
/*Второй поток t2 начнет выполнение только после того, How будет завершен
(or бросит исключение) первый поток - t1*/
try {
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
t2.start();
//Главный поток продолжит работу только после того, How t1 и t2 завершат работу
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Все потоки закончor работу, программа завершена");
}
}
Kami telah membuat kelas sederhana ThreadExample
. Tugasnya adalah menampilkan pesan di layar tentang dimulainya pekerjaan, kemudian tertidur selama 5 detik dan pada akhirnya menginformasikan selesainya pekerjaan. Tidak ada yang rumit. Logika utama terkandung di dalam kelas Main
. Lihat komentarnya: dengan menggunakan metode ini, join()
kami berhasil mengontrol urutan eksekusi utas. Jika Anda ingat awal topik, penjadwal thread melakukan ini. Dia meluncurkannya atas kebijakannya sendiri: berbeda setiap saat. Di sini, dengan menggunakan metode ini, kami memastikan bahwa thread pertama akan diluncurkan dan dieksekusi t1
, kemudian thread t2
, dan hanya setelahnya thread utama eksekusi program. Teruskan. Dalam program nyata, Anda akan sering menghadapi situasi ketika Anda perlu menghentikan eksekusi suatu thread. Misalnya thread kita sedang berjalan, namun menunggu event atau kondisi tertentu terpenuhi. Jika ini terjadi, maka berhenti. Mungkin logis jika ada beberapa metode seperti stop()
. Namun, semuanya tidak sesederhana itu. Suatu ketika, sebuah metode Thread.stop()
di Java benar-benar ada dan memungkinkan Anda untuk menghentikan pekerjaan sebuah thread. Namun kemudian dihapus dari perpustakaan Java. Anda dapat mencarinya di dokumentasi Oracle dan melihat bahwa itu ditandai sebagai deprecated . Mengapa? Karena itu hanya menghentikan aliran tanpa ada pekerjaan tambahan. Misalnya, sebuah thread dapat bekerja dengan data dan mengubah sesuatu di dalamnya. Kemudian dia tiba-tiba pingsan stop()
di tengah pekerjaan - dan hanya itu. Tidak ada penghentian yang benar, tidak ada pembebasan sumber daya, bahkan tidak ada penanganan kesalahan - semua ini tidak terjadi. Metode ini stop()
, jika dibesar-besarkan, hanya menghancurkan segala sesuatu yang dilewatinya. Pengoperasiannya dapat dibandingkan dengan bagaimana seseorang mencabut steker dari stopkontak untuk mematikan komputer. Ya, Anda dapat mencapai hasil yang diinginkan. Tetapi semua orang memahami bahwa dalam beberapa minggu komputer tidak akan mengucapkan "terima kasih" untuk ini. Karena alasan ini, logika untuk menginterupsi thread di Java telah diubah, dan sekarang metode khusus digunakan - interrupt()
.
Metode Thread.interrupt()
Apa yang terjadi jika Anda memanggil metodeinterrupt()
pada thread ? Ada 2 pilihan:
- Jika objek berada dalam keadaan menunggu pada saat itu, misalnya,
join
atausleep
, maka menunggu akan terganggu dan program akan berhentiInterruptedException
. - Jika thread dalam keadaan berfungsi pada saat itu, tanda boolean objek akan disetel
interrupted
.
Thread
memiliki metode khusus - boolean isInterrupted()
. Mari kita kembali ke contoh jam dari kuliah utama. Untuk kenyamanan, ini sedikit disederhanakan:
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("Работа потока была прервана");
break;
}
System.out.println("Tik");
}
}
}
Dalam kasus kami, jam mulai dan mulai berdetak setiap detik. Pada detik ke 10 kita menghentikan aliran jam. Seperti yang telah Anda ketahui, jika thread yang ingin kita interupsi berada dalam salah satu status tunggu, maka ini akan menghasilkan InterruptedException
. Jenis pengecualian ini adalah pengecualian yang dicentang, sehingga dapat dengan mudah ditangkap dan logika penghentian program kita dijalankan. Itulah yang kami lakukan. Inilah hasil kami: Tik Tik Tik Tik Tik Tik Tik Tik Tik Pekerjaan thread terhenti. Ini mengakhiri pengenalan kami pada metode utama kelas Thread
. Untuk memantapkan pengetahuan Anda, Anda dapat menonton video ceramah tentang multithreading ini:
GO TO FULL VERSION