Mukadimah. Pakcik Petya
Jadi, katakan kami ingin mengisi sebotol air. Sebotol dan paip air Uncle Petya disediakan. Pakcik Petya memasang paip baru hari ini, dan dia terus memuji keindahannya. Sebelum itu, dia hanya menggunakan paip lama yang tersumbat, jadi garisan di pembotolan sangat besar. Setelah meraba-raba sedikit, kedengaran bunyi isi air dari arah tumpahan, selepas 2 minit botol masih dalam tahap pengisian, barisan biasa sudah berkumpul di belakang kami, dan imej di kepala saya adalah betapa prihatinnya pakcik. Petya hanya memilih molekul H2O terbaik ke dalam botol kami. Pakcik Petya, dilatih oleh kehidupan, menenangkan mereka yang sangat agresif dan berjanji untuk menyelesaikannya secepat mungkin. Setelah selesai dengan botol, dia mengambil yang seterusnya dan menghidupkan tekanan biasa, yang tidak mendedahkan semua keupayaan paip baru. Orang tak senang...
Teori
Multithreading ialah keupayaan platform untuk mencipta berbilang benang dalam satu proses. Mencipta dan melaksanakan utas adalah lebih mudah daripada mencipta proses, jadi jika perlu untuk melaksanakan beberapa tindakan selari dalam satu program, utas tambahan digunakan. Dalam JVM, sebarang program berjalan dalam utas utama, dan selebihnya dilancarkan daripadanya. Dalam proses yang sama, benang dapat bertukar-tukar data antara satu sama lain. Apabila memulakan utas baharu, anda boleh mengisytiharkannya sebagai utas pengguna menggunakan kaedah tersebut
setDaemon(true);
utas tersebut akan ditamatkan secara automatik jika tiada lagi utas berjalan yang tinggal. Benang mempunyai keutamaan kerja (pilihan keutamaan tidak menjamin bahawa utas keutamaan tertinggi akan selesai lebih cepat daripada utas keutamaan lebih rendah).
- MIN_PRIORITY
- NORM_PRIORITY (lalai)
- MAX_PRIORITY
Kaedah asas apabila bekerja dengan aliran:
run()
– melaksanakan benang
start()
– memulakan benang
getName()
– mengembalikan nama utas
setName()
– menentukan nama aliran
wait()
– kaedah diwarisi, utas menunggu kaedah dipanggil notify()
dari utas lain
notify()
– kaedah yang diwarisi, menyambung semula benang yang dihentikan sebelum ini
notifyAll()
– kaedah yang diwarisi, menyambung semula benang yang dihentikan sebelum ini
sleep()
– menjeda strim untuk masa tertentu
join()
– menunggu benang selesai
interrupt()
– mengganggu pelaksanaan benang
Lebih banyak kaedah boleh didapati
di sini. Sudah tiba masanya untuk memikirkan urutan baharu jika program anda mempunyai:
- Akses rangkaian
- Akses sistem fail
- GUI
Kelas benang
Benang di Jawa diwakili sebagai kelas
Thread
dan keturunannya. Contoh di bawah ialah pelaksanaan mudah kelas aliran.
import static java.lang.System.out;
public class ExampleThread extends Thread{
public static void main(String[] args) {
out.println("Основной поток");
new ExampleThread().start();
}
@Override
public void run() {
out.println("Новый поток");
}
}
Hasilnya kita dapat
Основной поток
Новый поток
Di sini kami mencipta kelas kami dan menjadikannya turunan class
Thread
, selepas itu kami menulis kaedah main() untuk melancarkan utas utama dan mengatasi kaedah
run()
kelas
Thread
. Sekarang, setelah mencipta contoh kelas kami dan melaksanakan kaedah yang diwarisinya,
start()
kami akan melancarkan utas baharu di mana semua yang diterangkan dalam badan kaedah akan dilaksanakan
run()
. Kedengarannya rumit, tetapi melihat kod contoh semuanya harus jelas.
Antara Muka Boleh Dijalankan
Oracle juga mencadangkan untuk melaksanakan antara muka untuk memulakan utas baharu
Runnable
, yang memberikan kami lebih banyak fleksibiliti reka bentuk daripada satu-satunya warisan yang tersedia dalam contoh sebelumnya (jika anda melihat sumber kelas
Thread
anda dapat melihat bahawa ia juga melaksanakan antara muka
Runnable
). Mari gunakan kaedah yang disyorkan untuk mencipta urutan baharu.
import static java.lang.System.out;
public class ExampleRunnable implements Runnable {
public static void main(String[] args) {
out.println("Основной поток");
new Thread(new ExampleRunnable()).start();
}
@Override
public void run() {
out.println("Новый поток");
}
}
Hasilnya kita dapat
Основной поток
Новый поток
Contoh-contohnya sangat serupa, kerana Semasa menulis kod, kami terpaksa melaksanakan kaedah abstrak
run()
yang diterangkan dalam antara muka
Runnable
. Melancarkan utas baharu sedikit berbeza. Kami mencipta contoh kelas
Thread
dengan menghantar rujukan kepada contoh pelaksanaan antara muka kami sebagai parameter
Runnable
. Pendekatan inilah yang membolehkan anda mencipta utas baharu tanpa mewarisi kelas secara langsung
Thread
.
Operasi yang panjang
Contoh berikut akan menunjukkan dengan jelas faedah menggunakan berbilang benang. Katakan kita mempunyai tugas mudah yang memerlukan beberapa pengiraan yang panjang, sebelum artikel ini kita akan menyelesaikannya dalam kaedah,
main()
mungkin memecahkannya kepada kaedah berasingan untuk memudahkan persepsi, mungkin juga kelas, tetapi intipatinya akan sama. Semua operasi akan dilakukan secara berurutan satu demi satu. Mari kita simulasi pengiraan berat dan ukur masa pelaksanaannya.
public class ComputeClass {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
for(double i = 0; i < 999999999; i++){
}
System.out.println("complete 1");
for(double i = 0; i < 999999999; i++){
}
System.out.println("complete 2");
for(double i = 0; i < 999999999; i++){
}
System.out.println("complete 3");
long timeSpent = System.currentTimeMillis() - startTime;
System.out.println("программа выполнялась " + timeSpent + " миллисекунд");
}
}
Hasilnya kita dapat
complete 1
complete 2
complete 3
программа выполнялась 9885 миллисекунд
Masa pelaksanaan meninggalkan banyak yang diingini, dan selama ini kami melihat skrin keluaran kosong, dan keadaannya sangat mirip dengan cerita tentang Uncle Petya, hanya sekarang dalam peranannya kami, pemaju, tidak mengambil kesempatan daripada semua keupayaan peranti moden. Kami akan menambah baik.
public class ComputeClass {
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
new MyThread(1).start();
new MyThread(2).start();
for(double i = 0; i < 999999999; i++){
}
System.out.println("complete 3");
long timeSpent = System.currentTimeMillis() - startTime;
System.out.println("программа выполнялась " + timeSpent + " миллисекунд");
}
}
class MyThread extends Thread{
int n;
MyThread(int n){
this.n = n;
}
@Override
public void run() {
for(double i = 0; i < 999999999; i++){
}
System.out.println("complete " + n);
}
}
Hasilnya kita dapat
complete 1
complete 2
complete 3
программа выполнялась 3466 миллисекунд
Masa berjalan telah dikurangkan dengan ketara (kesan ini mungkin tidak dapat dicapai atau mungkin meningkatkan masa pelaksanaan pada pemproses yang tidak menyokong multithreading). Perlu diingat bahawa rangkaian mungkin berakhir dengan tidak teratur, dan jika pembangun memerlukan kebolehramalan tindakan, dia mesti melaksanakannya secara bebas untuk kes tertentu.
Kumpulan benang
Thread dalam Java boleh digabungkan ke dalam kumpulan; kelas digunakan untuk ini
ThreadGroup
. Kumpulan boleh merangkumi kedua-dua urutan tunggal dan keseluruhan kumpulan. Ini boleh menjadi mudah jika anda perlu mengganggu aliran yang berkaitan, contohnya, dengan rangkaian apabila sambungan terputus. Anda boleh membaca lebih lanjut tentang kumpulan
di sini Saya harap topik ini telah menjadi lebih jelas kepada anda dan pengguna anda akan gembira.
GO TO FULL VERSION