Masalah yang dipecahkan multithreading di Java
Pada dasarnya, multithreading Java diciptakan untuk memecahkan dua masalah utama:-
Lakukan beberapa tindakan secara bersamaan.
Dalam contoh di atas, berbagai thread (yaitu anggota keluarga) melakukan beberapa tindakan secara paralel: mencuci piring, pergi ke toko, melipat barang.
Contoh yang lebih “programmer” dapat diberikan. Bayangkan Anda memiliki sebuah program dengan antarmuka pengguna. Ketika tombol Lanjutkan diklik, beberapa perhitungan akan terjadi dalam program, dan pengguna akan melihat layar antarmuka berikut. Jika tindakan ini dilakukan secara berurutan, setelah mengklik tombol "Lanjutkan", program akan terhenti begitu saja. Pengguna akan melihat layar yang sama dengan tombol “Lanjutkan” hingga semua perhitungan internal selesai dan program mencapai bagian di mana antarmuka akan mulai digambar.
Baiklah, mari kita tunggu beberapa menit!
Kita juga dapat membuat ulang program kita, atau, seperti yang dikatakan oleh programmer, “memparalelkan.” Biarkan perhitungan yang diperlukan dilakukan di satu thread, dan rendering antarmuka di thread lain. Sebagian besar komputer memiliki sumber daya yang cukup untuk ini. Dalam hal ini, program tidak akan "bodoh", dan pengguna akan dengan tenang berpindah antar layar antarmuka tanpa mengkhawatirkan apa yang terjadi di dalamnya. Itu tidak mengganggu :)
-
Mempercepat perhitungan.
Semuanya jauh lebih sederhana di sini. Jika prosesor kami memiliki beberapa inti, dan sebagian besar prosesor sekarang multi-inti, daftar tugas kami dapat diselesaikan secara paralel dengan beberapa inti. Jelasnya, jika kita perlu menyelesaikan 1000 masalah dan masing-masing masalah diselesaikan dalam satu detik, satu inti akan menyelesaikan daftar tersebut dalam 1000 detik, dua inti dalam 500 detik, tiga inti hanya dalam waktu 333 detik, dan seterusnya.
Thread
. Artinya, untuk membuat dan menjalankan 10 thread, Anda memerlukan 10 objek kelas ini. Mari kita tulis contoh paling sederhana:
public class MyFirstThread extends Thread {
@Override
public void run() {
System.out.println("I'm Thread! My name is " + getName());
}
}
Untuk membuat dan meluncurkan thread, kita perlu membuat kelas dan mewarisinya dari java.lang
. Thread
dan ganti metode di dalamnya run()
. Yang terakhir ini sangat penting. Di dalam metode itulah run()
kita menentukan logika yang harus dijalankan oleh thread kita. Sekarang, jika kita membuat sebuah instance MyFirstThread
dan menjalankannya, metode ini run()
akan mencetak baris dengan namanya ke konsol: metode ini getName()
akan mencetak nama “sistem” dari thread, yang ditetapkan secara otomatis. Meskipun sebenarnya mengapa “jika”? Ayo buat dan uji!
public class Main {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
MyFirstThread thread = new MyFirstThread();
thread.start();
}
}
}
Keluaran konsol: Saya Thread! Nama saya Thread-2 Saya Thread! Nama saya Thread-1 Saya Thread! Nama saya Thread-0 Saya Thread! Nama saya Thread-3 Saya Thread! Nama saya Thread-6 Saya Thread! Nama saya Thread-7 Saya Thread! Nama saya Thread-4 Saya Thread! Nama saya Thread-5 Saya Thread! Nama saya Thread-9 Saya Thread! Nama saya Thread-8 Kami membuat 10 thread (objek) MyFirstThread
yang diwarisi Thread
dan meluncurkannya dengan memanggil metode objek start()
. Setelah memanggil suatu metode , start()
metodenya mulai bekerja run()
, dan logika yang tertulis di dalamnya dijalankan. Harap diperhatikan: nama thread tidak berurutan. Cukup aneh, kenapa tidak dieksekusi secara bergantian: Thread-0
, Thread-1
, Thread-2
dan seterusnya? Ini adalah contoh ketika pemikiran standar dan “berurutan” tidak akan berhasil. Faktanya adalah dalam hal ini kami hanya mengeluarkan perintah untuk membuat dan meluncurkan 10 thread. Urutan peluncurannya ditentukan oleh penjadwal thread: mekanisme khusus di dalam sistem operasi. Bagaimana sebenarnya strukturnya dan berdasarkan prinsip apa ia mengambil keputusan adalah topik yang sangat kompleks, dan kami tidak akan mendalaminya sekarang. Hal utama yang perlu diingat adalah programmer tidak dapat mengontrol urutan eksekusi thread. Untuk menyadari keseriusan situasi ini, coba jalankan metode main()
dari contoh di atas beberapa kali lagi. Keluaran konsol kedua: Saya Thread! Nama saya Thread-0 Saya Thread! Nama saya Thread-4 Saya Thread! Nama saya Thread-3 Saya Thread! Nama saya Thread-2 Saya Thread! Nama saya Thread-1 Saya Thread! Nama saya Thread-5 Saya Thread! Nama saya Thread-6 Saya Thread! Nama saya Thread-8 Saya Thread! Nama saya Thread-9 Saya Thread! Nama saya Thread-7 Output konsol ketiga: Saya Thread! Nama saya Thread-0 Saya Thread! Nama saya Thread-3 Saya Thread! Nama saya Thread-1 Saya Thread! Nama saya Thread-2 Saya Thread! Nama saya Thread-6 Saya Thread! Nama saya Thread-4 Saya Thread! Nama saya Thread-9 Saya Thread! Nama saya Thread-5 Saya Thread! Nama saya Thread-7 Saya Thread! Nama saya Thread-8
Masalah yang ditimbulkan oleh multithreading
Dalam contoh buku, Anda melihat bahwa multithreading memecahkan masalah yang cukup penting, dan penggunaannya mempercepat kerja program kami. Dalam banyak kasus - berkali-kali. Namun bukan tanpa alasan bahwa multithreading dianggap sebagai topik yang kompleks. Lagi pula, jika digunakan secara tidak benar, hal itu malah menimbulkan masalah, bukan menyelesaikannya. Saat saya mengatakan “menciptakan masalah”, yang saya maksud bukanlah sesuatu yang abstrak. Ada dua masalah spesifik yang dapat disebabkan oleh multithreading: kebuntuan dan kondisi balapan. Deadlock adalah situasi di mana beberapa thread menunggu sumber daya ditempati satu sama lain, dan tidak ada satupun yang dapat melanjutkan eksekusi. Kita akan membicarakannya lebih lanjut pada kuliah berikutnya, tapi untuk saat ini contoh ini sudah cukup: Bayangkan thread-1 bekerja dengan beberapa Objek-1, dan thread-2 bekerja dengan Objek-2. Programnya ditulis seperti ini:- Thread-1 akan berhenti bekerja dengan Objek-1 dan beralih ke Objek-2 segera setelah Thread-2 berhenti bekerja dengan Objek 2 dan beralih ke Objek-1.
- Thread-2 akan berhenti bekerja dengan Objek-2 dan beralih ke Objek-1 segera setelah Thread-1 berhenti bekerja dengan Objek 1 dan beralih ke Objek-2.
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();
}
}
}
Sekarang bayangkan program tersebut bertanggung jawab atas pengoperasian robot yang menyiapkan makanan! Thread-0 mengeluarkan telur dari lemari es. Aliran 1 menyalakan kompor. Stream-2 mengeluarkan penggorengan dan menaruhnya di atas kompor. Aliran 3 menyalakan api di atas kompor. Stream 4 menuangkan minyak ke dalam wajan. Stream 5 memecahkan telur dan menuangkannya ke dalam penggorengan. Stream 6 melempar cangkangnya ke tempat sampah. Stream-7 mengeluarkan telur orak-arik yang sudah jadi dari api. Potok-8 menaruh telur orak-arik di piring. Aliran 9 mencuci piring. Lihatlah hasil program kita: Thread-0 dieksekusi Thread-2 thread dieksekusi Thread-1 thread dieksekusi Thread-4 thread dieksekusi Thread-9 thread dieksekusi Thread-5 thread dieksekusi Thread-8 thread dieksekusi Thread-7 thread dieksekusi Thread-7 thread dieksekusi -3 Thread-6 thread dieksekusi Apakah skripnya menyenangkan? :) Dan semua itu karena pengoperasian program kita bergantung pada urutan eksekusi thread. Sedikit saja pelanggaran urutannya, dapur kita berubah menjadi neraka, dan robot yang menjadi gila menghancurkan segala sesuatu di sekitarnya. Ini juga merupakan masalah umum dalam pemrograman multithread, yang akan Anda dengar lebih dari sekali. Di akhir kuliah, saya ingin merekomendasikan Anda sebuah buku tentang multithreading.
GO TO FULL VERSION