Menggunakan mode threading swingworker
Sangat penting bagi pengembang ayunan untuk menggunakan konkurensi dengan hati -hati. Program ayunan yang baik menggunakan mekanisme konkurensi untuk membuat antarmuka pengguna yang tidak kehilangan respons - tidak peduli apa pun interaksi pengguna, program ini selalu dapat meresponsnya. Untuk membuat program yang responsif, pengembang harus belajar cara menggunakan multithreading dalam kerangka kerja ayunan.
Pengembang ayunan akan berurusan dengan jenis utas berikut:
(1) Utas awal, utas tersebut akan menjalankan kode aplikasi inisialisasi.
(2) Utas pengiriman acara, semua kode pemrosesan acara dieksekusi di sini. Sebagian besar kode yang berinteraksi dengan kerangka kerja ayunan harus menjalankan utas ini juga.
(3) Utas pekerja, juga dikenal sebagai latar belakang utas, akan melakukan semua tugas yang memakan waktu.
Pengembang tidak perlu membuat utas ini secara eksplisit dalam kode mereka: mereka disediakan oleh runtime atau swing framework. Tugas pengembang adalah menggunakan utas ini untuk membuat program ayunan yang responsif dan gigih.
Seperti semua program lain yang berjalan di platform Java, program ayunan dapat membuat utas tambahan dan kumpulan utas, yang membutuhkan penggunaan pendekatan yang akan diperkenalkan dalam artikel ini. Artikel ini akan memperkenalkan tiga utas di atas. Diskusi utas pekerja akan melibatkan penggunaan kelas javax.swing.swingworker. Kelas ini memiliki banyak fitur yang berguna, termasuk komunikasi dan kolaborasi antara tugas utas pekerja dan tugas utas lainnya.
1. Utas awal
Setiap program menghasilkan serangkaian utas di awal logika aplikasi. Dalam program standar, hanya ada satu utas seperti itu: utas ini akan memanggil metode utama di kelas utama program. Dalam applet, utas awal adalah konstruktor dari objek applet, yang akan memanggil metode init; Tindakan ini dapat dieksekusi dalam satu utas, atau dalam dua atau tiga utas yang berbeda, semuanya tergantung pada implementasi spesifik platform Java. Pada artikel ini, kami menyebut jenis utas awal utas ini.
Dalam program ayunan, tidak banyak yang bisa dilakukan di utas awal. Tugas paling mendasar mereka adalah membuat objek yang dapat dijalankan yang menginisialisasi GUI dan mengatur objek yang digunakan untuk menjalankan acara di utas pengiriman acara. Setelah GUI dibuat, program ini akan didorong terutama oleh peristiwa GUI, yang masing -masing akan menyebabkan pelaksanaan suatu peristiwa di utas pengiriman acara. Kode program dapat mengatur tugas tambahan untuk utas yang digerakkan oleh peristiwa (asalkan mereka dieksekusi dengan cepat sehingga mereka tidak mengganggu pemrosesan peristiwa) atau membuat utas pekerja (digunakan untuk melakukan tugas yang memakan waktu).
Tugas Pembuatan Benang Awal Orkestrasi GUI adalah dengan menelepon javax.swing.swingutilities.invokelater atau javax.swing.swingutilities.invokeandwait. Kedua metode mengambil parameter yang unik: Runnable digunakan untuk menentukan tugas baru. Satu -satunya perbedaan di antara mereka adalah: Invokerlater hanya mengatur tugas dan pengembalian; Invokeandwait akan menunggu tugas dieksekusi sebelum kembali.
Lihat contoh berikut:
Swingutilities.invokelater (runnable baru ()) {public void run () {createandshowgui (); }} Dalam applet, tugas membuat GUI harus dimasukkan ke dalam metode init dan menggunakan invokeandwait; Jika tidak, proses awal akan dimungkinkan sebelum GUI dibuat, yang dapat menyebabkan masalah. Dalam kasus lain, tugas pembuatan orkestrasi GUI biasanya yang terakhir di utas awal yang akan dieksekusi, sehingga keduanya menggunakan Invokelater atau Invokokeandwait.
Mengapa utas awal tidak membuat GUI secara langsung? Karena hampir semua kode yang digunakan untuk membuat dan berinteraksi dengan komponen ayunan harus dieksekusi di utas pengiriman acara. Kendala ini akan dibahas di bawah ini.
2. Utas distribusi acara
Kode pemrosesan acara ayunan dieksekusi di utas khusus, yang disebut utas pengiriman acara. Sebagian besar kode yang memanggil metode ayunan dijalankan di utas ini. Ini diperlukan karena sebagian besar objek ayunan adalah "aman non-utas".
Anda dapat menganggap eksekusi kode sebagai melakukan serangkaian tugas pendek di utas pengiriman acara. Sebagian besar tugas dipanggil dengan metode penanganan acara, seperti ActionListener.actionperformed. Tugas yang tersisa akan diatur oleh kode program, menggunakan Invokelater atau Invokokeandwait. Tugas dalam utas pengiriman acara harus dapat dieksekusi dengan cepat. Kalau tidak, peristiwa yang tidak diproses akan ditimbulkan dan antarmuka pengguna akan menjadi "responsif".
Jika Anda perlu menentukan apakah kode Anda dieksekusi di utas pengiriman acara, hubungi javax.swing.swingutilities.iseventDispatchThread.
3. Benang Pekerja dan Swingworker
Ketika program ayunan perlu melakukan tugas yang panjang, biasanya akan dilakukan dengan menggunakan utas pekerja. Setiap tugas dijalankan di utas pekerja, yang merupakan contoh dari kelas Javax.Swing.Swingworker. Kelas SwingWorker adalah kelas abstrak; Anda harus mendefinisikan subkelasnya untuk membuat objek SwingWorker; Biasanya menggunakan kelas dalam anonim untuk melakukan ini.
SwingWorker menyediakan beberapa fitur komunikasi dan kontrol:
(1) Subclass dari Swingworker dapat mendefinisikan metode, dilakukan. Ketika tugas latar belakang selesai, itu akan secara otomatis dipanggil oleh utas pengiriman acara.
(2) Kelas Swingworker mengimplementasikan java.util.concurrent.future. Antarmuka ini memungkinkan tugas latar belakang untuk memberikan nilai pengembalian ke utas lain. Metode dalam antarmuka ini juga menyediakan fungsi yang memungkinkan kehancuran tugas latar belakang dan menentukan apakah tugas latar belakang telah diselesaikan atau dicabut.
(3) Tugas latar belakang dapat memberikan hasil perantara dengan memanggil SwingWorker.publish, dan utas pengiriman acara akan memanggil metode ini.
(4) Tugas latar belakang dapat menentukan sifat pengikatan. Perubahan dalam atribut yang mengikat akan memicu peristiwa, dan utas pengiriman acara akan menghubungi penangan acara untuk menangani peristiwa yang dipicu ini.
4. Tugas Backend Sederhana
Berikut adalah contohnya, tugas ini sangat sederhana, tetapi merupakan tugas yang berpotensi memakan waktu. Applet Tumbleitem mengimpor serangkaian file gambar. Jika file gambar ini diimpor melalui utas awal, akan ada penundaan sebelum GUI muncul. Jika file gambar ini diimpor di utas pengiriman acara, GUI mungkin gagal untuk merespons.
Untuk menyelesaikan masalah ini, kelas Tumblumeem membuat dan menjalankan instance dari kelas StringWorker saat diinisialisasi. Metode doinbackground dari objek ini dieksekusi di utas pekerja, mengimpor gambar ke dalam array Imageicon, dan mengembalikan referensi ke sana. Kemudian metode yang dilakukan dieksekusi di utas pengiriman acara, dapatkan referensi yang dikembalikan, dan letakkan di variabel anggota IMG dari kelas applet. Melakukan ini memungkinkan kelas Tumblumeem untuk membuat GUI segera tanpa harus menunggu impor gambar untuk menyelesaikannya.
Kode sampel berikut mendefinisikan dan mengimplementasikan objek SwingWorker.
SwingWorker Worker = SwingWorker baru <ImageIcon [], void> () {@Override public Imageicon [] doinbackground () {final ImageIcon [] INNERIMGS = Imageicon baru [NIMGS]; untuk (int i = 0; i <nimgs; i ++) {innerimgs [i] = loadImage (i+1); } return innerimgs; } @Override public void done () {// Hapus label "memuat gambar". animator.removeall (); loopslot = -1; coba {imgs = get (); } catch (InterruptedException abaikan) {} catch (java.util.concurrent.executionException e) {string Why = null; Penyebab yang dapat dilempar = e.getCause (); if (cause! = null) {why = cause.getMessage (); } else {why = e.getMessage (); } System.err.println ("File pengambilan kesalahan:" + mengapa); }}}}; Semua subclass yang diwarisi dari Swingworker harus mengimplementasikan doinbackground; Implementasi metode yang dilakukan adalah opsional.
Perhatikan bahwa SwingWorker adalah kelas paradigma dengan dua parameter. Parameter tipe pertama menentukan jenis pengembalian doinbackground. Ini juga merupakan jenis metode GET, yang dapat dipanggil oleh utas lain untuk mendapatkan nilai pengembalian dari doinbackground. Parameter tipe kedua menentukan jenis hasil perantara. Contoh ini tidak mengembalikan hasil perantara, sehingga diatur ke batal.
Menggunakan metode GET, Anda dapat membuat referensi ke objek IMGS (dibuat di utas pekerja) digunakan di utas pengiriman acara. Ini memungkinkan berbagi objek antar utas.
Sebenarnya ada dua cara untuk mengembalikan objek oleh kelas doinbackground.
(1) Tidak ada parameter untuk memanggil swingworker.get. Jika tugas latar tidak selesai, metode GET akan diblokir sampai selesai.
(2) Hubungi swingworker.get dengan parameter untuk menentukan batas waktu. Jika tugas latar tidak selesai, blokir sampai selesai - kecuali jika batas waktu berakhir, dalam hal ini dapatkan akan melempar java.util.concurrent.TimeOutException.
5. Tugas dengan Hasil Menengah
Berguna untuk memiliki tugas backend yang berfungsi memberikan hasil menengah. Tugas backend dapat menghubungi Metode SwingWorker.Publish untuk melakukan ini. Metode ini menerima banyak parameter. Setiap parameter harus satu yang ditentukan oleh parameter tipe swingworker kedua.
SwingWorker.Process dapat menggantikan untuk menyimpan hasil yang disediakan oleh metode publikasi. Metode ini disebut oleh utas pengiriman acara. Hasil yang ditetapkan dari metode publikasi biasanya dikumpulkan dengan metode proses.
Mari kita lihat contoh yang disediakan oleh Filper.java. Program ini menghasilkan serangkaian tes boolean acak java.util.random melalui tugas latar belakang. Ini seperti percobaan lemparan koin. Untuk melaporkan hasilnya, tugas latar belakang menggunakan objek Flippair.
kelas statis pribadi flippair {private final long head, total; Flippair (kepala panjang, total panjang) {this.heads = heads; this.total = total; }} Kepala mewakili hasil dari true; Total mewakili jumlah total lemparan.
Program latar belakang adalah instance dari Filptask:
Flipkask kelas pribadi memperluas swingworker <void, flippair> {
Karena tugas tidak mengembalikan hasil akhir, tidak perlu menentukan apa parameter tipe pertama, gunakan void. Setelah masing -masing "melempar", tugas memanggil Publish:
@Overrideprotected void doinbackground () {long head = 0; Total panjang = 0; Acak acak = acak baru (); while (! isCancelled ()) {total ++; if (random.nextBoolean ()) {heads ++; } publikasi (flippair baru (kepala, total)); } return null;} Karena publikasi sering disebut, banyak nilai Flippair akan dikumpulkan sebelum metode proses disebut oleh utas pengiriman acara; Proses ini hanya berfokus pada set nilai terakhir yang dikembalikan setiap kali, dan menggunakannya untuk memperbarui GUI:
Proses void yang dilindungi (pasangan daftar) {flippair pair = pairs.get (pairs.size () - 1); headstext.setText (string.format ("%d", pair.heads)); totalText.setText (string.format ("%d", pair.total)); devtext.setText (string.format ("%. 10g", ((double) pair.heads)/((double) pair.total) - 0,5));} 6. Batalkan tugas latar belakang
Hubungi SwingWorker.Cancel untuk membatalkan tugas latar belakang yang mengeksekusi. Tugas harus konsisten dengan mekanisme undo sendiri. Ada dua cara untuk melakukan ini:
(1) Ketika interupsi diterima, itu akan diakhiri.
(2) Hubungi Swingworker. Jika panggilan swingworker membatalkan, metode ini akan mengembalikan true.
7. Bind Atribut dan Metode Negara
Swingworker mendukung properti terikat, yang sangat berguna saat berkomunikasi dengan utas lain. Menyediakan dua properti yang mengikat: kemajuan dan status. Kemajuan dan status dapat digunakan untuk memicu tugas pemrosesan acara di utas pengiriman acara.
Dengan mengimplementasikan pendengar perubahan properti, program dapat menangkap perubahan dalam kemajuan, negara bagian atau properti mengikat lainnya.
7.1 Variabel terikat kemajuan
Variabel pengikatan kemajuan adalah variabel integer dengan kisaran 0 hingga 100. Ini telah ditentukan sebelumnya (metode swingworker yang dilindungi.
7.2 Variabel terikat negara bagian
Perubahan dalam variabel pengikatan negara mencerminkan proses mengubah objek Swingworker selama siklus hidupnya. Variabel ini berisi jenis enumerasi swingworker.statevalue. Nilai yang mungkin adalah:
(1) tertunda
Keadaan ini berlangsung untuk sementara waktu untuk mengetahui dari penciptaan objek yang disebut metode doinbackground.
(2) dimulai
Keadaan ini berlangsung sejenak sebelum metode doinbackground dipanggil sampai metode selesai dipanggil.
(3) selesai
Sisa waktu objek akan tetap ada di negara bagian ini.
Jika Anda perlu mengembalikan nilai keadaan saat ini, Anda dapat menghubungi swingworker.getState.
7.3 Metode
Dua metode yang disediakan oleh antarmuka di masa depan juga dapat melaporkan status tugas latar belakang. Jika tugas dibatalkan, ISCancelled Returns True. Selanjutnya, jika tugas selesai, yaitu selesai secara normal atau dibatalkan, Isdone mengembalikan true.
Menggunakan wadah tingkat atas
Swing menyediakan 3 kelas kontainer tingkat atas: JFrame, JDialog, Japplet. Saat menggunakan tiga kelas ini, Anda harus memperhatikan poin -poin berikut:
(1). Untuk ditampilkan di layar, setiap komponen GUI harus menjadi bagian dari hierarki yang mengandung. Hirarki inklusi adalah struktur pohon komponen, dan wadah tingkat atas adalah akarnya.
(2). Setiap komponen GUI hanya dapat dimasukkan sekali. Jika komponen sudah ada dalam wadah dan kemudian mencoba menambahkannya ke wadah baru, komponen akan dihapus dari wadah pertama dan ditambahkan ke wadah kedua.
(3). Setiap wadah tingkat atas memiliki panel konten. Secara umum, panel konten ini akan berisi (secara langsung atau tidak langsung) semua komponen visual GUI wadah tingkat atas.
(4). Anda dapat menambahkan bilah menu ke wadah atas. Biasanya bilah menu ini ditempatkan di wadah atas, tetapi di luar panel konten.
1. Wadah tingkat atas dan hierarki inklusi
Setiap program yang menggunakan komponen ayunan memiliki setidaknya satu wadah tingkat atas. Wadah tingkat atas ini adalah simpul root yang berisi hierarki-hierarki ini akan berisi semua komponen ayunan yang akan muncul dalam wadah tingkat atas ini.
Biasanya, aplikasi berbasis GUI ayunan terpisah memiliki setidaknya satu hierarki inklusi dan simpul root-nya adalah jFrame. Misalnya, jika suatu aplikasi memiliki satu jendela dan dua kotak dialog, aplikasi akan memiliki tiga level inklusi, yaitu, akan ada tiga wadah tingkat atas. Hirarki penahanan mengambil jFrame sebagai simpul root, dan dua hierarki penahanan lainnya masing -masing memiliki jDialog sebagai simpul rootnya.
Sebuah applet yang didasarkan pada komponen ayunan berisi setidaknya satu hierarki inklusi, dan dapat ditentukan bahwa salah satunya harus dibuat dengan japplet sebagai simpul root -nya. Misalnya, applet dengan kotak dialog, ia akan memiliki dua level inklusi. Komponen di jendela browser akan ditempatkan dalam hierarki penahanan, dan simpul root -nya adalah objek Japplet. Kotak dialog akan memiliki hierarki yang mengandung, dan simpul root -nya adalah objek JDialog.
2. Tambahkan komponen ke panel konten
Operasi kode berikut adalah untuk mendapatkan panel konten bingkai dalam contoh di atas dan menambahkan label kuning:
frame.getContentPane (). Tambah (YellowLabel, BorderLayout.Center);
Seperti yang ditunjukkan dalam kode, Anda harus terlebih dahulu menemukan panel konten dari wadah tingkat atas dan mengimplementasikannya melalui metode GetContentPane. Panel konten default adalah wadah perantara sederhana, yang mewarisi dari jComponent, menggunakan BorderLayout sebagai manajer panelnya.
Menyesuaikan panel konten sederhana - Siapkan manajer panel atau tambahkan perbatasan. Harus dicatat di sini bahwa metode GetContentPane akan mengembalikan objek kontainer, bukan objek JComponent. Ini berarti bahwa jika Anda perlu memanfaatkan beberapa fungsionalitas jComponent, Anda juga harus mengetik konversi nilai pengembalian atau membuat komponen Anda sendiri sebagai panel konten. Contoh kami biasanya menggunakan metode kedua. Karena metode kedua lebih jelas dan lebih jelas. Cara lain yang kadang-kadang kita gunakan adalah dengan hanya menambahkan komponen yang ditentukan sendiri ke panel konten untuk sepenuhnya menutupi panel konten.
Jika Anda membuat panel konten Anda sendiri, berhati -hatilah untuk memastikan itu buram. Jpanel buram akan menjadi pilihan yang baik. Perhatikan bahwa secara default, tata letak JPanel dikelola sebagai Flowlayout, dan Anda mungkin ingin menggantinya dengan manajer tata letak lain.
Agar komponen menjadi panel konten, Anda perlu menggunakan metode setContentPane dari wadah tingkat atas, misalnya:
// Buat panel dan tambahkan komponen ke it.jpanel contentPane = jpanel baru (borderlayout baru ()); contentpane.setborder (someborder); contentpane.add (somecomponent, borderlayout.center); contentPane.add (lain contentPonent, borderlayout.page_end); pane.//contentpane.setopaque(true);toplevelcontainer.setContentPane(contentpane);
Catatan: Jangan gunakan wadah transparan sebagai panel konten, seperti jscrollpane, jsplitpane, dan jtabbedpane. Panel konten transparan akan menyebabkan komponen menjadi bingung. Meskipun Anda dapat membuat komponen ayunan transparan apik melalui metode SetOpaque (True), itu tidak akan terlihat benar ketika beberapa komponen diatur untuk sepenuhnya buram. Misalnya, panel tag.
3. Menambahkan bilah menu
Secara teori, setiap wadah tingkat atas dapat memiliki bilah menu. Tetapi fakta menunjukkan bahwa bilah menu hanya muncul di bingkai atau applet. Untuk menambahkan bilah menu ke wadah tingkat atas, Anda perlu membuat objek JMenubar, merakit beberapa menu, dan kemudian hubungi metode SetJMenubar. Contoh ToplevelDemo menambahkan bilah menu ke bingkai melalui kode berikut.
frame.setjmenubar (cyanmenubar);
4. Panel akar
Setiap wadah tingkat atas bergantung pada wadah perantara implisit yang disebut wadah akar. Wadah root ini mengelola panel konten dan bilah menu, bersama dengan dua atau lebih wadah lainnya (lihat panel berlapis, dll.). Anda biasanya tidak perlu tahu tentang menggunakan wadah root komponen ayunan. Namun, jika Anda ingin mencegat klik mouse atau menggambar pada beberapa komponen, Anda perlu mengetahui wadah root.
Di atas telah dijelaskan tentang panel konten dan bilah menu opsional, dan tidak akan diulangi di sini. Dua komponen lainnya yang terkandung dalam wadah akar adalah panel tata letak dan panel kaca. Panel tata letak langsung berisi panel menu dan panel konten, dan memungkinkan Anda untuk mengurutkan komponen lain yang ditambahkan oleh koordinat z. Panel kaca biasanya digunakan untuk mencegat tindakan input yang terjadi di lapisan atas dan juga dapat digunakan untuk menggambar pada beberapa komponen.