1. Utas dan proses
1. Apa perbedaan antara utas dan proses:
Utas mengacu pada unit eksekusi yang dapat menjalankan kode program selama eksekusi. Dalam bahasa Java, utas memiliki empat negara bagian: jalankan, siap, menangguhkan dan mengakhiri.
Suatu proses mengacu pada program yang sedang dieksekusi. Benang juga menjadi proses yang ringan ketika ada hubungannya. Mereka memiliki unit eksekusi program terkecil. Suatu proses dapat memiliki banyak utas. Setiap utas berbagi ruang daya internal program (segmen kode, segmen data dan ruang tumpukan) dan beberapa sumber daya tingkat proses (seperti file terbuka), tetapi setiap utas memiliki ruang sendiri.
2. Mengapa menggunakan multi-proses ? <BR /> Ada terutama aspek-aspek berikut di tingkat sistem operasi:
- Menggunakan multi-threading dapat mengurangi waktu respons program. Jika suatu operasi memakan waktu, atau terjebak dalam menunggu lama, program tidak akan menanggapi operasi seperti mouse dan keyboard. Setelah menggunakan multi-threading, utas yang memakan waktu ini dapat dialokasikan ke utas terpisah untuk dieksekusi, sehingga membuat program interaktivitas yang lebih baik.
- Pembuatan utas dan overhead switching lebih murah dibandingkan dengan proses, sedangkan multithreading sangat efisien dalam berbagi data.
-Komputer multi-CPU atau multi-core memiliki kemampuan untuk menjalankan multi-thread. Jika satu proses digunakan, sumber daya komputer tidak akan digunakan kembali, menghasilkan pemborosan sumber daya yang sangat besar. Menggunakan multithreading pada komputer multi-CPU dapat meningkatkan pemanfaatan CPU.
- Menggunakan multithreading dapat menyederhanakan struktur program dan memudahkan untuk dipahami dan dipelihara.
2. Membuat utas <br /> Ada umumnya tiga metode untuk implementasi multi-threading, dan dua yang pertama adalah metode yang paling umum digunakan:
1. Mewariskan kelas utas dan mengesampingkan metode run ()
Thread pada dasarnya adalah instance yang mengimplementasikan antarmuka runnable. Perlu dicatat bahwa setelah memanggil metode start (), itu tidak segera menjalankan kode multi-threaded segera, tetapi sebaliknya membuat utas dijalankan. Kapan menjalankan kode multi-threaded ditentukan oleh sistem operasi.
Inilah langkah utamanya:
(1) Tentukan subclass dari kelas utas dan ganti metode run dari kelas. Badan metode metode run mewakili tugas yang ingin diselesaikan oleh utas. Oleh karena itu, metode run () disebut badan eksekusi.
(2) Buat instance subkelas utas, yaitu, buat objek utas.
(3) Panggil metode start () dari objek utas untuk memulai utas.
TestThread kelas publik memperluas utas {public void run () {System.out.println ("Hello World"); } public static void main (string [] args) {thread mthread = new testThread (); mthread.start (); }} 2. Menerapkan antarmuka runnable dan mengimplementasikan metode run () dari antarmuka
Inilah langkah utamanya:
(1) Kustomisasi kelas dan terapkan antarmuka runnable, dan terapkan metode run ().
(2) Buat instance dari subkelas utas dan instantiate objek utas dengan objek yang mengimplementasikan antarmuka runnable sebagai parameter.
(3) Metode call thread start () untuk memulai utas.
kelas publik testRunnable mengimplementasikan runnable {public void run () {System.out.println ("Hello World"); }} kelas publik testRunnable {public static void main (string [] args) {testRunnable mTestrunnable = new testRunnable (); Utas mthread = utas baru (mTestrunnable); mthread.start (); }} 3. Menerapkan antarmuka yang dapat dipanggil dan mengganti metode panggilan ()
Antarmuka yang dapat dipanggil sebenarnya adalah kelas fungsional dalam kerangka kerja pelaksana. Antarmuka yang dapat dipanggil mirip dengan antarmuka yang dapat dijalankan, tetapi menyediakan fungsi yang lebih kuat daripada Runnable, yang terutama dimanifestasikan dalam 3 poin berikut:
(1) Callable dapat memberikan nilai pengembalian setelah tugas diterima, dan runnable tidak dapat memberikan fungsi ini.
(2) Metode panggilan () dalam Callable dapat melempar pengecualian, sedangkan metode run () runnable tidak dapat melempar pengecualian.
(3) Menjalankan Callable bisa mendapatkan objek di masa depan. Objek masa depan mewakili hasil perhitungan Ibrahimovic, dan ia menyediakan metode untuk memeriksa apakah perhitungan selesai. Karena utas tersebut termasuk dalam model perhitungan asinkron, tidak mungkin untuk mendapatkan nilai pengembalian fungsi dari utas lain. Dalam hal ini, masa depan dapat digunakan untuk memantau metode panggilan () ketika utas target memanggil metode panggilan (). Namun, ketika metode GET () di masa depan dipanggil untuk mendapatkan hasilnya, utas saat ini akan memblokir dan mengetahui hasil pengembalian dari metode panggilan ().
Public Class TestCallable {// Buat kelas utas kelas statis public myTestCallable mengimplementasikan callable {public string call () melempar Exception {retun "Hello World"; }} public static void main (string [] args) {mytestCallable mmytestcallable = mytestcallable baru (); ExecutorService mexecutorService = executors.newsinglethreadpool (); Masa depan mfuture = mexecutorservice.submit (mmytestcallable); Coba {// menunggu utas untuk mengakhiri dan mengembalikan hasil system.out.println (mfuture.get ()); } catch (Exception e) {E.PrintStackTrace (); }}}Hasil output dari program di atas adalah: halo dunia
Di antara ketiga metode ini, umumnya disarankan untuk mengimplementasikan antarmuka yang dapat dilalui. Alasannya adalah: Pertama, kelas utas mendefinisikan berbagai metode yang dapat ditulis ulang oleh kelas yang diturunkan, tetapi hanya metode run () yang harus ditulis ulang, yang mewujudkan fungsi utama utas ini, yang juga merupakan metode yang diperlukan untuk mengimplementasikan antarmuka yang dapat dijalankan. Kedua, kelas harus diwarisi ketika mereka perlu diperkuat atau dimodifikasi. Oleh karena itu, jika tidak perlu mengesampingkan metode lain dari kelas utas, lebih baik untuk mengimplementasikan antarmuka runnable dalam kasus ini.
3. Benang interupsi <br /> utas akan berakhir ketika metode utas menjalankan () mengeksekusi pernyataan terakhir dalam badan metode dan kembali dengan mengeksekusi pernyataan pengembalian, atau ketika pengecualian yang tidak terperangkap dalam metode tidak ditangkap. Ada metode berhenti dalam versi Java sebelumnya, yang dapat dipanggil oleh utas lain untuk mengakhiri utas, tetapi metode ini sekarang sudah usang.
Metode interupsi dapat digunakan untuk meminta penghentian utas. Ketika utas memanggil metode interupsi, status interupsi utas akan ditetapkan. Ini adalah bendera boolean yang tidak dimiliki oleh utas. Setiap utas harus memeriksa bendera ini dari waktu ke waktu untuk menentukan apakah utas terganggu.
Untuk mengetahui apakah utas diatur, Anda dapat memanggil thread.currentThread (). IsInterrupted ():
while (! thread.currentThread (). is Intercrupted ()) {do something} Namun, jika utas diblokir, keadaan interupsi tidak dapat dideteksi. Di sinilah interruptedException dihasilkan. Ketika metode interupsi dipanggil pada benang yang diblokir (disebut tidur atau tunggu). Panggilan pemblokiran akan terganggu oleh ExterruptedException.
Jika metode tidur (atau metode gangguan lainnya) dipanggil setelah setiap iterasi, deteksi yang terputus tidak perlu dan tidak berguna. Jika metode tidur dipanggil ketika keadaan interupsi ditetapkan, itu tidak akan tidur tetapi akan membersihkan keadaan dan melempar Exception interrupted. Jadi, jika Anda menelepon tidur dalam satu loop, jangan mendeteksi status interupsi, tangkap saja ExcepedException.
Dalam banyak kode yang diterbitkan, Anda akan menemukan bahwa interupsi Exception ditekan pada level yang sangat rendah:
void mytask () {... coba {sleep (50)} catch (InterruptedException e) {...}}Jangan lakukan ini. Jika Anda tidak berpikir ada manfaat dalam tangkapan, ada dua opsi yang masuk akal:
Hubungi thread.currentThread (). Interrup () dalam tangkapan untuk mengatur status interupsi. Penelepon dapat mendeteksinya. Pilihan yang lebih baik adalah menggunakan Throw InterruptedException untuk menandai metode Anda, tanpa menggunakan blok pernyataan coba untuk menangkap yang selesai. Dengan cara ini penelepon dapat menangkap pengecualian ini:
void myTask () Throw InterruptedException {sleep (50)}4. Keadaan utas
(1). Status Baru (Baru): Objek utas baru dibuat.
(2). Status siap (runnable): Setelah objek utas dibuat, utas lain memanggil metode start () dari objek. Utas dalam keadaan ini terletak di kumpulan utas yang dapat dilalui dan menjadi dapat dikeluarkan, menunggu untuk mendapatkan hak penggunaan CPU.
(3). Status menjalankan: utas dalam keadaan siap memperoleh CPU dan menjalankan kode program.
(4). Status yang diblokir: Negara yang diblokir berarti bahwa utas tersebut menyerahkan hak penggunaan CPU untuk beberapa alasan dan sementara berhenti berjalan. Tidak sampai utas memasuki keadaan siap, ia memiliki kesempatan untuk pergi ke keadaan berjalan. Ada tiga jenis penyumbatan:
- Menunggu untuk memblokir: Benang yang berjalan mengeksekusi metode tunggu (), dan JVM akan memasukkan utas ke dalam kolam tunggu.
- Pemblokiran sinkron: Ketika utas yang berjalan memperoleh kunci sinkronisasi objek, jika kunci sinkronisasi ditempati oleh utas lain, JVM akan memasukkan utas ke dalam kumpulan kunci.
- Pemblokiran Lainnya: Ketika utas yang sedang berjalan mengeksekusi metode tidur () atau bergabung (), atau mengeluarkan permintaan I/O, JVM akan mengatur utas ke status pemblokiran. Ketika status tidur () diatur waktu, bergabung () menunggu utas untuk diakhiri atau diatur waktunya, atau pemrosesan I/O selesai, utas yang dimasukkan kembali ke keadaan siap.
(5). Status Mati: Utas telah selesai mengeksekusi atau keluar dari metode run () karena pengecualian, dan utas mengakhiri siklus hidupnya.
5. Thread Prioritas dan Daemon Thread
1. Prioritas utas
Di Java, setiap utas memiliki prioritas, dan secara default, utas mewarisi prioritas kelas induknya. Anda dapat menggunakan metode SetPriority untuk meningkatkan atau mengurangi prioritas utas apa pun. Prioritas dapat diatur ke nilai apa pun antara min_priority (didefinisikan sebagai 1 di kelas utas) dan max_priority (didefinisikan sebagai 10 di kelas utas). Prioritas default utas adalah norm_priority (didefinisikan sebagai 5 di kelas utas).
Cobalah untuk tidak mengandalkan prioritas. Jika Anda benar -benar ingin menggunakannya, Anda harus menghindari kesalahan umum yang dilakukan pemula. Jika beberapa utas prioritas tinggi tidak memasuki keadaan tidak aktif, utas prioritas rendah mungkin tidak akan pernah dieksekusi. Setiap kali penjadwal memutuskan untuk menjalankan utas baru, pertama-tama memilih di antara utas dengan prioritas, meskipun ini akan benar-benar kelaparan utas prioritas rendah.
2. Benang daemon
Hubungi setdaemon (true); Mengubah utas menjadi utas daemon. Satu -satunya tujuan utas daemon adalah untuk menyediakan layanan ke utas lain. Utas waktu adalah contoh. Ini mengirimkan sinyal ke utas lain secara teratur atau menghapus utas yang sudah ketinggalan zaman yang memberi tahu item cache. Ketika hanya benang daemon yang tersisa, mesin virtual keluar, karena jika hanya benang daemon yang tersisa, tidak perlu terus menjalankan program.
Selain itu, koleksi sampah JVM, manajemen memori dan utas lainnya adalah benang daemon. Juga, saat melakukan aplikasi basis data, kumpulan koneksi basis data yang digunakan juga berisi banyak utas latar belakang, memantau jumlah koneksi, waktu batas waktu, status, dll.
Di atas adalah tentang definisi utas, status dan sifat java multithreading. Saya berharap ini akan membantu untuk pembelajaran semua orang.