JavaRush /Blog Java /Random-MS /Multithreading di Jawa: intipati, kelebihan dan perangkap...

Multithreading di Jawa: intipati, kelebihan dan perangkap biasa

Diterbitkan dalam kumpulan
hello! Pertama sekali, tahniah: anda telah mencapai topik Multithreading di Jawa! Ini adalah pencapaian yang serius, masih jauh lagi. Tetapi bersedia: ini adalah salah satu topik yang paling sukar dalam kursus. Dan maksudnya bukanlah bahawa kelas kompleks atau banyak kaedah digunakan di sini: sebaliknya, tidak ada dua dozen pun. Ia lebih kepada anda perlu mengubah sedikit pemikiran anda. Sebelum ini, program anda telah dilaksanakan secara berurutan. Beberapa baris kod mengikuti yang lain, beberapa kaedah mengikuti yang lain, dan secara keseluruhan semuanya jelas. Mula-mula, hitung sesuatu, kemudian paparkan hasilnya pada konsol, kemudian tamatkan program. Untuk memahami multithreading, sebaiknya fikir dari segi concurrency. Mari kita mulakan dengan sesuatu yang sangat mudah :) Multithreading di Jawa: intipati, kelebihan dan perangkap biasa - 1Bayangkan keluarga anda sedang berpindah dari satu rumah ke rumah yang lain. Bahagian penting dalam bergerak ialah mengemas buku anda. Anda telah mengumpul banyak buku, dan anda perlu memasukkannya ke dalam kotak. Sekarang hanya anda yang bebas. Ibu sedang menyediakan makanan, abang sedang mengumpul pakaian, dan kakak telah pergi ke kedai. Sendirian anda boleh menguruskan, sekurang-kurangnya, dan, lambat laun, anda akan menyelesaikan tugas itu sendiri, tetapi ia akan mengambil banyak masa. Walau bagaimanapun, dalam 20 minit kakak anda akan kembali dari kedai, dan dia tidak mempunyai apa-apa lagi yang perlu dilakukan. Jadi dia boleh menyertai anda. Tugasnya tetap sama: masukkan buku ke dalam kotak. Ia hanya berjalan dua kali lebih pantas. kenapa? Kerana kerja dilakukan secara selari. Dua "benang" yang berbeza (anda dan kakak anda) melakukan tugas yang sama secara serentak dan, jika tiada apa-apa perubahan, perbezaan masa akan menjadi sangat besar berbanding dengan situasi di mana anda akan melakukan segala-galanya sendirian. Jika abang anda menyelesaikan tugasnya tidak lama lagi, dia boleh membantu anda, dan keadaan akan menjadi lebih cepat.

Masalah yang diselesaikan oleh multithreading di Jawa

Pada asasnya, multithreading Java dicipta untuk menyelesaikan dua masalah utama:
  1. Lakukan berbilang tindakan pada masa yang sama.

    Dalam contoh di atas, benang yang berbeza (iaitu ahli keluarga) melakukan beberapa tindakan secara selari: mencuci pinggan mangkuk, pergi ke kedai, melipat barang.

    Contoh yang lebih "pengaturcara" boleh diberikan. Bayangkan anda mempunyai program dengan antara muka pengguna. Apabila butang Teruskan diklik, beberapa pengiraan harus berlaku dalam program dan pengguna harus melihat skrin antara muka berikut. Jika tindakan ini dijalankan secara berurutan, selepas mengklik butang "Teruskan", program hanya akan membekukan. Pengguna akan melihat skrin yang sama dengan butang "Teruskan" sehingga semua pengiraan dalaman selesai dan program mencapai bahagian di mana antara muka akan mula dilukis.

    Baiklah, mari tunggu beberapa minit!

    Multithreading di Jawa: intipati, kelebihan dan perangkap biasa - 3

    Kami juga boleh membuat semula program kami, atau, seperti yang dikatakan pengaturcara, "sejajarkan." Biarkan pengiraan yang diperlukan dilakukan dalam satu utas, dan pemaparan antara muka dalam yang lain. Kebanyakan komputer mempunyai sumber yang mencukupi untuk ini. Dalam kes ini, program ini tidak akan menjadi "bodoh", dan pengguna akan bergerak dengan tenang antara skrin antara muka tanpa perlu risau tentang apa yang berlaku di dalamnya. Ia tidak mengganggu :)

  2. Mempercepatkan pengiraan.

    Segala-galanya lebih mudah di sini. Jika pemproses kami mempunyai beberapa teras, dan kebanyakan pemproses kini berbilang teras, senarai tugas kami boleh diselesaikan secara selari dengan beberapa teras. Jelas sekali, jika kita perlu menyelesaikan 1000 masalah dan setiap daripada mereka diselesaikan dalam satu saat, satu teras akan mengatasi senarai dalam 1000 saat, dua teras dalam 500 saat, tiga dalam lebih daripada 333 saat, dan seterusnya.

Tetapi, seperti yang telah anda baca dalam kuliah, sistem moden sangat pintar, dan walaupun pada satu teras pengkomputeran mereka dapat melaksanakan selari, atau pseudo-paralelisme, apabila tugas dilakukan secara bergilir-gilir. Mari kita beralih daripada perkara umum kepada perkara khusus dan berkenalan dengan kelas utama dalam perpustakaan Java yang berkaitan dengan multithreading - java.lang.Thread. Tegasnya, benang dalam Java diwakili oleh contoh kelas Thread. Iaitu, untuk mencipta dan menjalankan 10 utas, anda memerlukan 10 objek kelas ini. Mari tulis contoh paling mudah:
public class MyFirstThread extends Thread {

   @Override
   public void run() {
       System.out.println("I'm Thread! My name is " + getName());
   }
}
Untuk mencipta dan melancarkan benang, kita perlu mencipta kelas dan mewarisinya daripada java.lang. Threaddan mengatasi kaedah di dalamnya run(). Yang terakhir sangat penting. Ia adalah dalam kaedah yang run()kita menetapkan logik yang thread kita mesti melaksanakan. Sekarang, jika kita mencipta contoh MyFirstThreaddan menjalankannya, kaedah itu run()akan mencetak baris dengan namanya ke konsol: kaedah getName()mencetak nama "sistem" benang, yang ditetapkan secara automatik. Walaupun, sebenarnya, mengapa "jika"? Mari 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();
       }
   }
}
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 Kami mencipta 10 utas (objek) MyFirstThreadyang mewarisi Threaddan melancarkannya dengan memanggil kaedah objek start(). Selepas memanggil kaedah , start()kaedahnya mula berfungsi run(), dan logik yang ditulis di dalamnya dilaksanakan. Sila ambil perhatian: nama benang tidak teratur. Agak pelik, kenapa mereka tidak dibunuh secara bergilir-gilir: Thread-0, Thread-1, Thread-2dan seterusnya? Ini betul-betul contoh apabila pemikiran standard, "berurutan" tidak akan berfungsi. Hakikatnya ialah dalam kes ini kami hanya mengeluarkan arahan untuk mencipta dan melancarkan 10 utas. Dalam susunan apa mereka harus dilancarkan diputuskan oleh penjadual benang: mekanisme khas di dalam sistem pengendalian. Seberapa tepat ia distrukturkan dan atas prinsip apa ia membuat keputusan adalah topik yang sangat kompleks, dan kami tidak akan menyelaminya sekarang. Perkara utama yang perlu diingat ialah pengaturcara tidak dapat mengawal urutan pelaksanaan benang. Untuk menyedari keseriusan keadaan, cuba jalankan kaedah main()dari contoh di atas beberapa kali lagi. Output 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 dengan buku, anda melihat bahawa multithreading menyelesaikan masalah yang agak penting, dan penggunaannya mempercepatkan kerja program kami. Dalam banyak kes - banyak kali. Tetapi bukan untuk apa-apa bahawa multithreading dianggap sebagai topik yang kompleks. Lagipun, jika digunakan secara tidak betul, ia menimbulkan masalah dan bukannya menyelesaikannya. Apabila saya menyebut "cipta masalah," saya tidak bermaksud sesuatu yang abstrak. Terdapat dua masalah khusus yang boleh menyebabkan multithreading: kebuntuan dan keadaan perlumbaan. Kebuntuan ialah situasi di mana beberapa utas sedang menunggu sumber diduduki oleh satu sama lain, dan tiada satu pun daripada mereka boleh terus melaksanakan. Kami akan bercakap lebih lanjut mengenainya dalam kuliah akan datang, tetapi buat masa ini contoh ini sudah memadai: Multithreading di Jawa: intipati, kelebihan dan perangkap biasa - 4 Bayangkan bahawa thread-1 berfungsi dengan beberapa Objek-1, dan thread-2 berfungsi dengan Objek-2. Program ini ditulis seperti ini:
  1. Thread-1 akan berhenti berfungsi dengan Objek-1 dan bertukar kepada Objek-2 sebaik sahaja Thread-2 berhenti berfungsi dengan Objek 2 dan bertukar kepada Objek-1.
  2. Thread-2 akan berhenti berfungsi dengan Objek-2 dan bertukar kepada Objek-1 sebaik sahaja Thread-1 berhenti berfungsi dengan Objek 1 dan bertukar kepada Objek-2.
Walaupun tanpa pengetahuan mendalam tentang multithreading, anda boleh memahami dengan mudah bahawa tiada apa yang akan datang daripadanya. Benang tidak akan bertukar tempat dan akan menunggu antara satu sama lain selama-lamanya. Kesilapan nampak jelas, tetapi sebenarnya tidak. Anda boleh membenarkannya ke dalam program dengan mudah. Kami akan melihat contoh kod yang menyebabkan kebuntuan dalam kuliah berikut. Ngomong-ngomong, Quora mempunyai contoh kehidupan sebenar yang sangat baik yang menerangkan maksud kebuntuan . “Di beberapa negeri di India, mereka tidak akan menjual tanah pertanian kepada anda melainkan anda berdaftar sebagai petani. Bagaimanapun, anda tidak akan didaftarkan sebagai petani jika anda tidak memiliki tanah pertanian.” Hebat, apa yang boleh saya katakan! :) Sekarang tentang keadaan perlumbaan - keadaan perlumbaan. Multithreading di Jawa: intipati, kebaikan dan perangkap biasa - 5Keadaan perlumbaan ialah kecacatan reka bentuk dalam sistem atau aplikasi berbilang benang di mana pengendalian sistem atau aplikasi bergantung pada susunan bahagian kod dilaksanakan. Ingat contoh dengan menjalankan benang:
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 bahawa program itu bertanggungjawab untuk operasi robot yang menyediakan makanan! Thread-0 mengeluarkan telur dari peti sejuk. Aliran 1 menghidupkan dapur. Stream-2 mengeluarkan kuali dan meletakkannya di atas dapur. Aliran 3 menyalakan api di atas dapur. Aliran 4 tuang minyak ke dalam kuali. Aliran 5 pecahkan telur dan tuangkan ke dalam kuali. Aliran 6 membuang cengkerang ke dalam tong sampah. Stream-7 mengeluarkan telur hancur yang telah siap dari api. Potok-8 meletakkan telur hancur di atas pinggan. Stream 9 basuh pinggan. Lihat hasil program kami: Thread-0 executed Thread-2 thread executed Thread-1 thread executed Thread-4 thread executed Thread-9 thread executed Thread-5 thread executed Thread-8 thread executed Thread-7 thread executed Thread-7 thread executed -3 Thread-6 thread executed. Adakah skrip itu menyeronokkan? :) Dan semuanya kerana operasi program kami bergantung pada susunan di mana utas dilaksanakan. Dengan sedikit pun pelanggaran urutan, dapur kami bertukar menjadi neraka, dan robot yang menjadi gila memusnahkan segala-galanya di sekelilingnya. Ini juga merupakan masalah biasa dalam pengaturcaraan berbilang benang, yang akan anda dengar lebih daripada sekali. Pada akhir kuliah, saya ingin mengesyorkan anda sebuah buku mengenai multithreading.
Multithreading di Jawa: intipati, kebaikan dan perangkap biasa - 6
"Java Concurrency dalam Amalan" telah ditulis pada tahun 2006, tetapi tidak kehilangan kaitannya. Ia merangkumi pengaturcaraan berbilang benang dalam Java, bermula dari asas dan berakhir dengan senarai ralat dan antipattern yang paling biasa. Jika anda pernah membuat keputusan untuk menjadi guru pengaturcaraan berbilang benang, buku ini mesti dibaca. Jumpa anda di kuliah seterusnya! :)
Komen
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION