Pertama, mari kita bicara tentang pengetahuan konseptual yang terkait dengan aplikasi dan proses di Java, dan kemudian jelaskan cara membuat utas dan cara membuat proses. Berikut adalah garis besar direktori dari artikel ini:
1. KONCEPTS Terkait dengan aplikasi dan proses di Java
2. Cara membuat utas di java
3. Bagaimana membuat proses di java
1. KONCEPTS Terkait dengan aplikasi dan proses di Java
Di Java, aplikasi sesuai dengan instance JVM (juga disebut proses JVM), dan nama default ke java.exe atau javaw.exe (dapat dilihat melalui manajer tugas di bawah windows). Java mengadopsi model pemrograman tunggal, yaitu, jika kita tidak secara aktif membuat utas dalam program kita sendiri, kita hanya akan membuat satu utas, yang biasanya disebut utas utama. Tetapi ketahuilah bahwa meskipun hanya ada satu utas untuk melakukan tugas tidak berarti bahwa hanya ada satu utas di JVM. Saat membuat instance JVM, banyak utas lainnya akan dibuat (seperti utas pengumpul sampah).
Karena Java mengadopsi model pemrograman tunggal, ketika pemrograman UI, Anda harus memperhatikan menempatkan operasi yang memakan waktu di utas anak untuk menghindari memblokir utas utama (ketika pemrograman UI, utas utama adalah utas UI, yang digunakan untuk menangani peristiwa interaksi pengguna).
2. Cara membuat utas di java
Jika Anda ingin membuat utas di Java, umumnya ada dua cara: 1) mewarisi kelas utas; 2) Menerapkan antarmuka runnable.
1. Mewariskan kelas utas
Jika Anda mewarisi kelas utas, Anda harus mengganti metode run dan menentukan tugas yang perlu dieksekusi dalam metode RUN.
kelas mythread memperluas utas {private static int num = 0; mythread publik () {num ++; } @Override public void run () {System.out.println ("secara aktif dibuat"+num+"thread"); }}Setelah membuat kelas utas Anda sendiri, Anda dapat membuat objek utas dan kemudian memulai utas melalui metode start (). Perhatikan bahwa tidak disebut metode run () untuk memulai utas. Metode jalankan hanya mendefinisikan tugas yang perlu dieksekusi. Jika metode run dipanggil, itu setara dengan mengeksekusi metode run di utas utama, yang tidak berbeda dari panggilan metode biasa. Pada saat ini, utas baru tidak akan dibuat untuk menjalankan tugas yang ditentukan.
tes kelas publik {public static void main (string [] args) {mythread thread = new mythread (); thread.start (); }} class mythread memperluas utas {private static int num = 0; mythread publik () {num ++; } @Override public void run () {System.out.println ("secara aktif dibuat"+num+"thread"); }}Dalam kode di atas, dengan memanggil metode start (), utas baru akan dibuat. Untuk membedakan perbedaan antara panggilan metode start () dan run () panggilan metode, silakan lihat contoh berikut:
tes kelas publik {public static void main (string [] args) {System.out.println ("ID utas utama:"+thread.currentThread (). getId ()); Mythread thread1 = mythread baru ("thread1"); thread1.start (); Mythread thread2 = mythread baru ("thread2"); thread2.run (); }} class mythread memperluas utas {private string name; public mythread (nama string) {this.name = name; } @Override public void run () {System.out.println ("name:"+name+"ID utas anak:"+thread.currentThread (). GetId ()); }}Hasil Menjalankan:
Dari hasil output, kesimpulan berikut dapat ditarik:
1) ID utas Thread1 dan Thread2 berbeda, dan Thread2 dan ID utas utama sama, yang berarti bahwa panggilan metode run tidak akan membuat utas baru, tetapi akan langsung menjalankan metode run di utas utama, yang tidak berbeda dari panggilan metode biasa;
2) Meskipun metode start call of thread1 dipanggil sebelum metode run thread2, informasi tentang panggilan metode run thread2 adalah output terlebih dahulu, menunjukkan bahwa proses membuat utas baru tidak akan memblokir eksekusi selanjutnya dari utas utama.
2. Menerapkan antarmuka runnable
Selain mewarisi kelas utas, membuat utas di Java juga dapat mengimplementasikan fungsi serupa dengan mengimplementasikan antarmuka runnable. Menerapkan antarmuka runnable harus mengganti metode yang dijalankan.
Inilah contohnya:
tes kelas publik {public static void main (string [] args) {System.out.println ("ID utas utama:"+thread.currentThread (). getId ()); MyRunnable runnable = new myrunnable (); Thread thread = utas baru (runnable); thread.start (); }} kelas myRunnable mengimplementasikan runnable {public myrunnable () {} @Override public void run () {System.out.println ("ID subthread:"+thread.currentThread (). getId ()); }}Runnable berarti "tugas" dalam bahasa Cina. Seperti namanya, dengan mengimplementasikan antarmuka Runnable, kami mendefinisikan subtugas dan kemudian menyerahkan subtugas ke utas untuk dieksekusi. Perhatikan bahwa metode ini harus menggunakan Runnable sebagai parameter ke kelas utas, dan kemudian buat utas baru untuk menjalankan subtugas melalui metode start utas. Jika metode run runnable dipanggil, utas baru tidak akan dibuat, dan tidak ada perbedaan antara panggilan metode biasa ini.
Bahkan, jika Anda melihat kode sumber implementasi kelas utas, Anda akan menemukan bahwa kelas utas mengimplementasikan antarmuka yang dapat dijalankan.
Di Java, kedua metode ini dapat digunakan untuk membuat utas untuk menjalankan subtugas. Metode spesifik untuk dipilih tergantung pada kebutuhan Anda. Jika Anda secara langsung mewarisi kelas utas, itu mungkin terlihat lebih ringkas daripada mengimplementasikan antarmuka yang dapat dijalankan. Namun, karena Java hanya memungkinkan warisan tunggal, jika kelas khusus perlu mewarisi kelas lain, Anda hanya dapat memilih untuk mengimplementasikan antarmuka yang dapat dijalankan.
3. Bagaimana membuat proses di java
Di Java, ada dua cara untuk membuat proses, melibatkan total 5 kelas utama.
Metode pertama adalah membuat proses melalui metode runtime.exec (), dan metode kedua adalah membuat proses melalui metode start ProcessBuilder. Mari kita bicara tentang perbedaan dan koneksi antara kedua metode ini.
Hal pertama yang ingin saya bicarakan adalah kelas proses. Kelas proses adalah kelas abstrak. Terutama ada beberapa metode abstrak di dalamnya. Anda dapat mempelajari ini dengan melihat kode sumber kelas proses:
Terletak di jalur java.lang.process:
tes kelas publik {public static void main (string [] args) {System.out.println ("ID utas utama:"+thread.currentThread (). getId ()); MyRunnable runnable = new myrunnable (); Thread thread = utas baru (runnable); thread.start (); }} kelas myRunnable mengimplementasikan runnable {public myrunnable () {} @Override public void run () {System.out.println ("ID subthread:"+thread.currentThread (). getId ()); }}1) Buat proses melalui proses proses
ProcessBuilder adalah kelas terakhir yang memiliki dua konstruktor:
Perintah Public Final Class ProcessBuilder {Private List <String>; direktori file pribadi; peta pribadi <string, string> lingkungan; redirecterrorstream boolean pribadi; Public ProcessBuilder (Daftar <String> Command) {if (command == null) Lempar nullpointerException baru (); this.command = perintah; } public ProcessBuilder (command ... command) {this.Command = ArrayList baru <string> (command.length); untuk (command arg: command) this.Command.add (arg); } ......}Konstruktor melewati parameter perintah dari proses yang perlu dibuat. Konstruktor pertama memasukkan parameter perintah ke dalam daftar dan meneruskannya dalam bentuk string panjang yang tak terbatas.
Jadi mari kita terus melihat ke bawah. Seperti yang disebutkan sebelumnya, kami membuat proses baru melalui metode start ProcessBuilder. Mari kita lihat apa yang sebenarnya dilakukan dalam metode awal. Berikut ini adalah kode sumber implementasi spesifik dari metode start:
start proses publik () melempar ioException {// harus dikonversi ke array terlebih dahulu-daftar yang disediakan pengguna berbahaya // mungkin mencoba untuk bersirkit dengan check.string [] cmdarray = command.toArray (command.size ()); for (string arg: cmdarray) if (arg == null)); Jika perintah adalah prog empa = cmdarray [0]; SecurityManager Security = System.GetSecurityManager (); if (Security! = Null) Security.checkexec (prog); String dir = directory == null? null: directory.tostring (); Coba {return ProcessImpl.Start (cmdarray, lingkungan, dir, redirecterrorstream);} catch (ioException e) {// Jauh lebih mudah bagi kita untuk membuat kesalahan berkualitas tinggi // pesan daripada kode C tingkat rendah yang menemukan masalahnya. Lempar ioException baru ("tidak dapat menjalankan program /" " + prog +" /"" + (dir == null? "": "(dalam direktori /" " + dir +" /")") + ":" + e.getMessage (), e);}}Metode ini mengembalikan objek proses. Bagian pertama dari metode ini setara dengan mengatur beberapa parameter berdasarkan parameter perintah dan direktori kerja yang ditetapkan. Yang paling penting adalah kalimat dalam blok pernyataan coba:
Return ProcessImpl.Start (CMDarray, Environment, Dir, RedirecterrorStream);
Ini adalah kalimat yang benar -benar menciptakan proses. Perhatikan bahwa metode awal dari kelas ProcessImpl dipanggil. Di sini kita dapat mengetahui bahwa awal harus menjadi metode statis. Jadi proses apa itu? Kelas ini juga terletak di jalur java.lang.processimpl. Mari kita lihat implementasi spesifik dari kelas ini:
ProcessImpl juga merupakan kelas akhir, yang mewarisi kelas proses:
Proses Kelas Akhir Memperluas Proses {// Bagian yang tergantung pada sistem dari ProcessBuilder.Start () statis statis (string cmdarray [], java.util.map <string, string> lingkungan, string dir, redirecterrorstream) lemparan ioException {stringblock = processenvent.toRenonRorREm) (ViVeronvonon (string {stringblock = processenVent.toRenvent (UNVERVENIONCOMON (UNVERNONMONIONCONMIONMIONMIONMIONMIONMIONMIONMIONCIONT (STRINGBLOCKLOCK = ProcessenVent. Return New ProcessImpl (CMDarray, Envblock, Dir, RedirecterrorStream); } ....}Ini adalah implementasi spesifik dari metode awal dari kelas ProcessImpl. Faktanya, kalimat ini digunakan untuk membuat objek ProcessImpl:
Return New ProcessImpl (CMDarray, Envblock, Dir, RedirecterrorStream);
Dalam ProcessImpl, beberapa metode abstrak di kelas proses diimplementasikan dalam implementasi konkret.
Bahkan, objek ProcessImpl dibuat melalui metode awal proses proses.
Mari kita lihat contoh menggunakan ProcessBuilder untuk membuat proses. Misalnya, jika saya ingin memulai proses melalui ProcessBuilder untuk membuka CMD dan mendapatkan informasi alamat IP, maka saya dapat menulisnya seperti ini:
tes kelas publik {public static void main (string [] args) melempar ioException {ProcessBuilder pb = new ProcessBuilder ("cmd", "/c", "ipconfig/all"); Proses proses = pb.start (); Pemindai Pemindai = Pemindai Baru (Process.GetInputStream ()); while (scanner.hasnextline ()) {System.out.println (scanner.nextline ()); } scanner.close (); }}Langkah pertama adalah yang paling kritis, yaitu untuk meneruskan string perintah ke konstruktor ProcessBuilder. Secara umum, setiap perintah independen dalam string digunakan sebagai parameter terpisah, tetapi juga dapat ditempatkan dalam daftar secara berurutan dan diteruskan.
Adapun banyak penggunaan spesifik lainnya, saya tidak akan menguraikannya di sini, seperti pengaturan variabel lingkungan proses dan direktori kerja melalui metode dan direktori lingkungan ProcessBuilder (direktori file). Teman yang tertarik dapat melihat dokumen API yang relevan.
2) Buat proses melalui metode eksekutif runtime
Pertama, mari kita lihat implementasi spesifik dari kelas runtime dan metode EXEC. Runtime, seperti namanya, berarti berjalan, mewakili instance mesin virtual di mana proses saat ini berada.
Karena proses apa pun hanya akan berjalan dalam satu instance mesin virtual, mode singleton digunakan dalam runtime, yaitu, hanya satu instance mesin virtual yang akan dihasilkan:
runtime kelas publik {private static runtime currentRuntime = runtime baru (); /*** Mengembalikan objek runtime yang terkait dengan aplikasi Java saat ini. * Sebagian besar metode kelas <code> runtime </code> adalah metode * dan harus dipanggil sehubungan dengan objek runtime saat ini. * * @return Objek <code> runtime </code> yang terkait dengan aplikasi * Java saat ini. */ runtime statis public getRuntime () {return currentRuntime; } / ** Jangan biarkan orang lain instantiate kelas ini* / private runtime () {} ...}Dari sini, kita dapat melihat bahwa karena konstruktor kelas runtime bersifat pribadi, kita hanya bisa mendapatkan instance runtime melalui getRuntime. Selanjutnya, mari kita lihat lebih dekat pada implementasi metode EXEC. Ada beberapa implementasi kelebihan EXEC di runtime, tetapi akhir dari eksekusi adalah versi metode EXEC ini:
EXEC PROSES PUBLIK (String [] CMDArray, String [] Envp, File Dir) melempar ioException {return new ProcessBuilder (cmdarray) .environment (envp) .directory (dir) .start (); }Dapat ditemukan bahwa pada kenyataannya, jika proses tersebut dibuat melalui eksekutif kelas runtime, pada akhirnya dibuat melalui metode awal kelas ProcessBuilder.
Mari kita lihat contoh untuk melihat cara membuat proses melalui eksekutif runtime, atau contoh sebelumnya, hubungi CMD untuk mendapatkan informasi alamat IP:
tes kelas publik {public static void main (string [] args) melempar ioException {string cmd = "cmd"+"/c"+"ipconfig/all"; Proses proses = runtime.getRuntime (). Exec (cmd); Pemindai Pemindai = Pemindai Baru (Process.GetInputStream ()); while (scanner.hasnextline ()) {System.out.println (scanner.nextline ()); } scanner.close (); }}Perlu dicatat bahwa metode EXEC tidak mendukung parameter panjang yang tidak terbatas (ProcessBuilder mendukung parameter panjang tidak terbatas), sehingga parameter perintah harus disambung terlebih dahulu sebelum meneruskannya.
Saya akan berbicara tentang cara membuat utas dan proses di Java untuk saat ini. Teman yang tertarik dapat merujuk pada informasi yang relevan.