CodeGym /Java Blog /Acak /Multithreading di Jawa
John Squirrels
Level 41
San Francisco

Multithreading di Jawa

Dipublikasikan di grup Acak
Hai! Pertama-tama, selamat: Anda telah mencapai topik Multithreading di Java! Ini adalah pencapaian yang serius — Anda telah menempuh perjalanan jauh. Tetapi persiapkan diri Anda: ini adalah salah satu topik tersulit dalam kursus. Dan bukan karena kita menggunakan kelas yang kompleks atau banyak metode di sini: sebenarnya, kita akan menggunakan kurang dari dua puluh. Lebih dari itu Anda harus sedikit mengubah cara berpikir Anda. Sebelumnya, program Anda telah dijalankan secara berurutan. Beberapa baris kode mengikuti yang lain, beberapa metode mengikuti yang lain, dan semuanya pada dasarnya jelas. Pertama, kami menghitung sesuatu, lalu menampilkan hasilnya di konsol, lalu program berakhir. Untuk memahami multithreading, lebih baik berpikir dalam istilah paralelisme. Mari kita mulai dengan sesuatu yang cukup sederhana : ) Bayangkan keluarga Anda pindah dari satu rumah ke rumah lain. Mengumpulkan semua buku Anda akan menjadi bagian penting dari langkah ini. Anda telah mengumpulkan banyak buku, dan Anda harus memasukkannya ke dalam kotak. Saat ini, Anda satu-satunya yang tersedia. Ibu sedang menyiapkan makanan, kakak mengemasi pakaian, dan adik pergi ke toko. Sendirian, entah bagaimana Anda bisa mengaturnya. Cepat atau lambat, Anda akan menyelesaikan tugas itu sendiri, tetapi akan memakan banyak waktu. Namun, kakakmu akan kembali dari toko dalam 20 menit, dan dia tidak punya pekerjaan lain. Jadi dia bisa bergabung denganmu. Tugasnya tidak berubah: masukkan buku ke dalam kotak. Tapi itu dilakukan dua kali lebih cepat. Mengapa? Karena pekerjaan terjadi secara paralel. Dua 'utas' yang berbeda (Anda dan saudara perempuan Anda) melakukan tugas yang sama secara bersamaan. Dan jika tidak ada yang berubah, maka akan ada perbedaan waktu yang sangat besar dibandingkan dengan situasi di mana Anda melakukan semuanya sendiri. Jika saudara laki-laki menyelesaikan pekerjaannya segera, dia dapat membantu Anda dan segalanya akan berjalan lebih cepat.

Masalah diselesaikan dengan multithreading

Multithreading sebenarnya diciptakan untuk mencapai dua tujuan penting:
  1. Lakukan beberapa hal sekaligus.

    Pada contoh di atas, utas yang berbeda (anggota keluarga) melakukan beberapa tindakan secara paralel: mencuci piring, pergi ke toko, mengemas barang.

    Kami dapat menawarkan contoh yang lebih dekat hubungannya dengan pemrograman. Misalkan Anda memiliki program dengan antarmuka pengguna. Ketika Anda mengklik 'Lanjutkan' dalam program, beberapa perhitungan akan terjadi dan pengguna akan melihat layar berikut. Jika tindakan ini dilakukan secara berurutan, maka program hanya akan hang setelah pengguna mengklik tombol 'Lanjutkan'. Pengguna akan melihat layar dengan layar tombol 'Lanjutkan' hingga program melakukan semua perhitungan internal dan mencapai bagian di mana antarmuka pengguna disegarkan.

    Yah, saya kira kita akan menunggu beberapa menit!

    Multithreading di Jawa: apa itu, manfaat dan jebakan umum - 3

    Atau kita dapat mengerjakan ulang program kita, atau, seperti yang dikatakan programmer, 'memparalelkannya'. Mari kita lakukan perhitungan kita di satu utas dan menggambar antarmuka pengguna di utas lainnya. Sebagian besar komputer memiliki sumber daya yang cukup untuk melakukan ini. Jika kita mengambil rute ini, maka program tidak akan macet dan pengguna akan berpindah dengan mulus antar layar tanpa mengkhawatirkan apa yang terjadi di dalamnya. Yang satu tidak mengganggu yang lain :)

  2. Melakukan perhitungan lebih cepat.

    Semuanya jauh lebih sederhana di sini. Jika prosesor kami memiliki banyak inti, dan sebagian besar prosesor saat ini memilikinya, maka beberapa inti dapat menangani daftar tugas kami secara paralel. Jelas, jika kita perlu melakukan 1000 tugas dan masing-masing membutuhkan waktu satu detik, satu inti dapat menyelesaikan daftar dalam 1000 detik, dua inti dalam 500 detik, tiga inti dalam waktu lebih dari 333 detik, dll.

Tetapi seperti yang telah Anda baca dalam pelajaran ini, sistem saat ini sangat cerdas, dan bahkan pada satu inti komputasi pun dapat mencapai paralelisme, atau lebih tepatnya paralelisme semu, di mana tugas dilakukan secara bergantian. Mari beralih dari hal umum ke hal yang spesifik dan mengenal kelas paling penting dalam pustaka multithreading Java — java.lang.Thread. Sebenarnya, utas Java diwakili oleh turunan dari kelas Utas . Ini berarti bahwa untuk membuat dan menjalankan 10 utas, Anda memerlukan 10 instance dari 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 menjalankan thread, kita perlu membuat class, membuatnya mewarisi java.lang . Thread , dan ganti metode run() -nya . Persyaratan terakhir itu sangat penting. Dalam metode run() kita mendefinisikan logika untuk dieksekusi oleh utas kita. Sekarang, jika kita membuat dan menjalankan instance MyFirstThread , metode run() akan menampilkan baris dengan nama: metode getName() menampilkan nama 'sistem' thread, yang ditetapkan secara otomatis. Tetapi mengapa kita berbicara dengan ragu-ragu? Mari buat satu dan cari tahu!

public class Main {

   public static void main(String[] args) {

       for (int i = 0; i < 10; i++) {

           MyFirstThread thread = new MyFirstThread();
           thread.start();
       }
   }
}
Output 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 Mari kita buat 10 utas ( objek MyFirstThread , yang mewarisi Thread ) dan memulainya dengan memanggil metode start() pada setiap objek. Setelah memanggil metode start() , logika dalam metode run() dijalankan. Catatan: nama utas tidak berurutan. Sungguh aneh bahwa mereka tidak berurutan:, Utas-1 , Utas-2 , dan seterusnya? Seperti yang terjadi, ini adalah contoh saat pemikiran 'berurutan' tidak sesuai. Masalahnya adalah kami hanya menyediakan perintah untuk membuat dan menjalankan 10 utas. Penjadwal utas, mekanisme sistem operasi khusus, memutuskan urutan eksekusinya. Desain yang tepat dan strategi pengambilan keputusannya adalah topik untuk diskusi mendalam yang tidak akan kita selami saat ini. Hal utama yang perlu diingat adalah programmer tidak dapat mengontrol urutan eksekusi thread. Untuk memahami keseriusan situasinya, coba jalankan metode main() pada contoh di atas beberapa kali lagi. Keluaran konsol saat dijalankan kedua: Saya Benang! 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 Console keluaran dari proses ketiga: I'm 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 dibuat oleh multithreading

Dalam contoh kami dengan buku, Anda melihat bahwa multithreading menyelesaikan tugas yang sangat penting dan dapat membuat program kami lebih cepat. Seringkali berkali-kali lebih cepat. Tetapi multithreading dianggap sebagai topik yang sulit. Memang, jika digunakan secara tidak tepat, justru menimbulkan masalah alih-alih menyelesaikannya. Ketika saya mengatakan 'menciptakan masalah', saya tidak bermaksud dalam arti abstrak. Ada dua masalah khusus yang dapat dibuat oleh multithreading: kebuntuan dan kondisi balapan. Kebuntuan adalah situasi di mana banyak utas menunggu sumber daya dipegang satu sama lain, dan tidak ada yang dapat terus berjalan. Kami akan membicarakannya lebih lanjut di pelajaran selanjutnya. Contoh berikut sudah cukup untuk saat ini: Multithreading di Jawa: apa itu, manfaat dan jebakan umum - 4Bayangkan Thread-1 berinteraksi dengan beberapa Object-1, dan Thread-2 berinteraksi dengan Object-2. Selanjutnya program ditulis sedemikian rupa sehingga:
  1. Thread-1 berhenti berinteraksi dengan Objek-1 dan beralih ke Objek-2 segera setelah Thread-2 berhenti berinteraksi dengan Objek-2 dan beralih ke Objek-1.
  2. Thread-2 berhenti berinteraksi dengan Objek-2 dan beralih ke Objek-1 segera setelah Thread-1 berhenti berinteraksi dengan Objek-1 dan beralih ke Objek-2.
Bahkan tanpa pemahaman mendalam tentang multithreading, Anda dapat dengan mudah melihat bahwa tidak akan terjadi apa-apa. Utas tidak akan pernah berpindah tempat dan akan menunggu satu sama lain selamanya. Kesalahannya tampak jelas, tetapi kenyataannya tidak. Anda dapat dengan mudah melakukan ini dalam sebuah program. Kami akan mempertimbangkan contoh kode yang menyebabkan kebuntuan dalam pelajaran selanjutnya. Omong-omong, Quora memiliki contoh kehidupan nyata yang bagus yang menjelaskan kebuntuan apaadalah. 'Di beberapa negara bagian di India, mereka tidak akan menjual tanah pertanian kepada Anda kecuali Anda adalah petani terdaftar. Namun, mereka tidak akan mendaftarkan Anda sebagai petani jika Anda tidak memiliki tanah pertanian'. Besar! Apa yang bisa kita katakan?! :) Sekarang mari kita bicara tentang kondisi balapan. Kondisi balapan adalah kesalahan desain dalam sistem atau aplikasi multithreaded, di mana pengoperasian sistem atau aplikasi bergantung pada urutan bagian kode yang dijalankan. Ingat, contoh kami di mana kami memulai utas:

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();
       }
   }
}
Sekarang bayangkan program tersebut bertanggung jawab untuk menjalankan robot yang memasak makanan! Thread-0 mengeluarkan telur dari lemari es. Thread-1 menyalakan kompor. Thread-2 mengambil panci dan menaruhnya di atas kompor. Thread-3 menyalakan kompor. Thread-4 menuangkan minyak ke dalam wajan. Thread-5 memecahkan telur dan menuangkannya ke dalam wajan. Thread-6 membuang kulit telur ke tempat sampah. Thread-7 mengeluarkan telur yang sudah matang dari kompor. Thread-8 meletakkan telur yang sudah matang di atas piring. Thread-9 mencuci piring. Lihat hasil program kita: Thread dieksekusi: Thread-0 Thread 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-3 Apakah ini rutinitas komedi? :) Dan semua itu karena program kita bergantung pada urutan eksekusi utas. Mengingat pelanggaran sekecil apa pun dari urutan yang diperlukan, dapur kami berubah menjadi neraka, dan robot gila menghancurkan semua yang ada di sekitarnya. Ini juga merupakan masalah umum dalam pemrograman multithreaded. Anda akan mendengarnya lebih dari sekali. Sebagai penutup pelajaran ini, saya ingin merekomendasikan sebuah buku tentang multithreading. Multithreading di Jawa: apa itu, manfaat dan jebakan umum - 6'Java Concurrency in Practice' ditulis pada tahun 2006, namun tidak kehilangan relevansinya. Ini didedikasikan untuk pemrograman Java multithreaded - dari dasar hingga kesalahan dan antipattern yang paling umum. Jika suatu hari Anda memutuskan untuk menjadi guru multithreading, buku ini harus dibaca. Sampai jumpa di pelajaran selanjutnya! :)
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION