Ayunkan threading dan utas pengiriman acara

Sebelumnya 1 2 3 4 5 Halaman 5 Halaman 5 dari 5

Menjaga keamanan benang Swing

Langkah terakhir dalam membuat GUI Swing adalah memulainya. Cara yang benar untuk memulai GUI Ayun hari ini berbeda dari pendekatan awal Sun yang ditentukan. Berikut kutipan dari dokumentasi Sun lagi:

Setelah komponen Swing direalisasikan, semua kode yang mungkin memengaruhi atau bergantung pada status komponen tersebut harus dijalankan di thread pengiriman peristiwa.

Sekarang buang instruksi tersebut ke luar jendela, karena sekitar saat JSE 1.5 dirilis semua contoh di situs Sun berubah. Sejak saat itu, fakta yang tidak banyak diketahui bahwa Anda seharusnya selalu mengakses komponen Swing pada thread event-dispatch untuk memastikan keamanan thread / akses single-threaded. Alasan di balik perubahan itu sederhana: sementara program Anda mungkin mengakses komponen Swing dari thread event-dispatch sebelum komponen direalisasikan, inisialisasi Swing UI dapat memicu sesuatu untuk dijalankan pada thread event-dispatch sesudahnya, karena component / UI mengharapkan untuk menjalankan semuanya di thread event-dispatch. Memiliki komponen GUI yang berjalan pada utas yang berbeda merusak model pemrograman utas tunggal Swing.

Program dalam Listing 5 tidak terlalu realistis, tetapi berfungsi untuk menjelaskan maksud saya.

Kode 5. Mengakses status komponen Swing dari beberapa utas

import java.awt.*; import java.awt.event.*; import javax.swing.*; public class BadSwingButton { public static void main(String args[]) { JFrame frame = new JFrame("Title"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JButton button = new JButton("Press Here"); ContainerListener container = new ContainerAdapter() { public void componentAdded(final ContainerEvent e) { SwingWorker worker = new SwingWorker() { protected String doInBackground() throws InterruptedException { Thread.sleep(250); return null; } protected void done() { System.out.println("On the event thread? : " + EventQueue.isDispatchThread()); JButton button = (JButton)e.getChild(); String label = button.getText(); button.setText(label + "0"); } }; worker.execute(); } }; frame.getContentPane().addContainerListener(container); frame.add(button, BorderLayout.CENTER); frame.setSize(200, 200); try { Thread.sleep(500); } catch (InterruptedException e) { } System.out.println("I'm about to be realized: " + EventQueue.isDispatchThread()); frame.setVisible(true); } }

Perhatikan bahwa output menunjukkan beberapa kode yang berjalan di utas utama sebelum UI direalisasikan. Ini berarti bahwa kode inisialisasi berjalan di satu utas sementara kode UI lainnya berjalan di utas event-dispatch, yang merusak model akses utas tunggal Swing:

> java BadSwingButton On the event thread? : true I'm about to be realized: false

Program dalam Daftar 5 akan memperbarui label tombol dari pendengar wadah ketika tombol ditambahkan ke wadah. Untuk membuat skenario lebih realistis, bayangkan UI yang "menghitung" label di dalamnya dan menggunakan hitungan sebagai teks dalam judul bingkai. Secara alami, itu perlu memperbarui teks judul perbatasan di utas pengiriman acara. Untuk menyederhanakan program hanya memperbarui label satu tombol. Meskipun fungsinya tidak realistis, program ini menunjukkan masalah pada setiap program Swing yang telah ditulis sejak awal waktu Swing. (Atau setidaknya semua yang mengikuti model threading yang direkomendasikan ditemukan di javadocs dan tutorial online dari Sun Microsystems, dan bahkan di edisi awal buku pemrograman Swing saya sendiri.)

Ayunan threading dilakukan dengan benar

Cara untuk mendapatkan Ayunan yang benar adalah dengan melupakan diktum asli Sun. Jangan khawatir tentang apakah suatu komponen direalisasikan atau tidak. Jangan repot-repot mencoba menentukan apakah aman untuk mengakses sesuatu dari thread event-dispatch. Tidak pernah. Sebagai gantinya, buat seluruh UI di thread event-dispatch. Jika Anda menempatkan seluruh panggilan pembuatan UI di dalam EventQueue.invokeLater()semua akses selama inisialisasi dijamin akan dilakukan di thread event-dispatch. Sesederhana itu.

Daftar 6. Segala sesuatu di tempatnya

import java.awt.*; import java.awt.event.*; import javax.swing.*; public class GoodSwingButton { public static void main(String args[]) { Runnable runner = new Runnable() { public void run() { JFrame frame = new JFrame("Title"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JButton button = new JButton("Press Here"); ContainerListener container = new ContainerAdapter() { public void componentAdded(final ContainerEvent e) { SwingWorker worker = new SwingWorker() { protected String doInBackground() throws InterruptedException { return null; } protected void done() { System.out.println("On the event thread? : " + EventQueue.isDispatchThread()); JButton button = (JButton)e.getChild(); String label = button.getText(); button.setText(label + "0"); } }; worker.execute(); } }; frame.getContentPane().addContainerListener(container); frame.add(button, BorderLayout.CENTER); frame.setSize(200, 200); System.out.println("I'm about to be realized: " + EventQueue.isDispatchThread()); frame.setVisible(true); } }; EventQueue.invokeLater(runner); } }

Jalankan sekarang dan program di atas akan menunjukkan bahwa inisialisasi dan kode penampung sedang berjalan di thread event-dispatch:

> java GoodSwingButton I'm about to be realized: true On the event thread? : true

Kesimpulannya

Pekerjaan ekstra untuk membuat UI Anda di thread event-dispatch mungkin tampak tidak perlu pada awalnya. Setiap orang telah melakukannya dengan cara lain sejak permulaan waktu. Mengapa repot-repot berubah sekarang? Masalahnya, kami selalu melakukan kesalahan. Untuk memastikan komponen Swing Anda diakses dengan benar, Anda harus selalu membuat seluruh UI di thread event-dispatch, seperti yang ditunjukkan di sini:

Runnable runner = new Runnable() { public void run() { // ...create UI here... } } EventQueue.invokeLater(runner);

Memindahkan kode inisialisasi Anda ke thread event-dispatch adalah satu-satunya cara untuk memastikan bahwa GUI Swing Anda aman untuk thread. Ya, awalnya akan terasa canggung, tetapi biasanya kemajuan akan terasa.

John Zukowski telah bermain dengan Java selama lebih dari 12 tahun sekarang, setelah meninggalkan pola pikir C dan X-Windowsnya sejak lama. Dengan 10 buku tentang topik mulai dari Swing hingga koleksi hingga Java SE 6, John sekarang melakukan konsultasi teknologi strategis melalui bisnisnya, JZ Ventures, Inc.

Pelajari lebih lanjut tentang topik ini

  • Pelajari lebih lanjut tentang pemrograman Swing dan thread event-dispatch dari salah satu master pengembangan desktop Java: Chet Haase tentang memaksimalkan Swing dan Java 2D (podcast JavaWorld Java Technology Insider, Agustus 2007).
  • "Sesuaikan SwingWorker untuk meningkatkan GUI Swing" (Yexin Chen, JavaWorld, Juni 2003) menggali lebih dalam beberapa tantangan penguliran Ayunan yang dibahas dalam artikel ini dan menjelaskan bagaimana penyesuaian SwingWorkerdapat memberikan otot untuk bekerja di sekitarnya.
  • "Java dan penanganan acara" (Todd Sundsted, JavaWorld, Agustus 1996) adalah primer tentang penanganan acara di sekitar AWT.
  • "Mempercepat pemberitahuan pendengar" (Robert Hastings, JavaWorld, Februari 2000) memperkenalkan spesifikasi JavaBeans 1.0 untuk pendaftaran dan pemberitahuan acara.
  • "Capai kinerja yang kuat dengan utas, Bagian 1" (Jeff Friesen, JavaWorld, Mei 2002) memperkenalkan utas Java. Lihat Bagian 2 untuk jawaban atas pertanyaan: Mengapa kita membutuhkan sinkronisasi?
  • "Menjalankan tugas dalam utas" adalah kutipan JavaWorld dari Java Concurrency in Practice (Brian Goetz, dkk., Addison Wesley Professional, Mei 2006) yang mendorong pemrograman utas berbasis tugas dan memperkenalkan kerangka kerja eksekusi untuk manajemen tugas.
  • "Threads and Swing" (Hans Muller dan Kathy Walrath, April 1998) adalah salah satu referensi resmi paling awal untuk swing threading. Ini mencakup "aturan utas tunggal" yang sekarang terkenal (dan keliru).
  • Membuat GUI dengan JFC / Swing adalah halaman Tutorial Java yang komprehensif untuk pemrograman GUI Swing.
  • "Concurrency in Swing" adalah tutorial tentang jalur Swing yang mencakup pengenalan SwingWorkerkelas.
  • JSR 296: Kerangka Aplikasi Ayun saat ini spesifikasi sedang berlangsung. Lihat juga "Menggunakan Kerangka Aplikasi Swing" (John O'Conner, Sun Developer Network, Juli 2007) untuk mempelajari lebih lanjut tentang langkah selanjutnya dalam evolusi pemrograman GUI Swing.
  • Seluruh Referensi AWT Java (John Zukowski, O'Reilly, Maret 1997) tersedia gratis dari Katalog Online O'Reilly.
  • Panduan Definitif John untuk Java Swing, Edisi Ketiga (Apress, Juni 2005) sepenuhnya diperbarui untuk Java Standard Edition versi 5.0. Baca bab pratinjau dari buku di sini di JavaWorld !
  • Kunjungi pusat penelitian JavaWorld Swing / GUI untuk artikel lebih lanjut tentang pemrograman Swing dan pengembangan desktop Java.
  • Lihat juga forum pengembang JavaWorld untuk diskusi dan Tanya Jawab terkait pemrograman desktop Swing dan Java.

Artikel ini, "Ayunkan benang dan acara pengiriman benang" awalnya diterbitkan oleh JavaWorld.