Swing: Membuat Thread Pekerja Keras Dan Tetap Responsif?


Setelah berulang kali membuat interface dengan Swing, aku cukup sering mendapatkan tulisan “Warning: Swing is not thread safe” di javadoc. Program dengan GUI Swing yang dibuat tanpa memperhatikan threading mungkin akan jalan dengan lancar, tapi ada kemungkinan ia akan bertingkah aneh suatu hari atau menjadi tidak responsif, dan kesalahan-kesalahan seperti ini sulit direproduksi. Dan masih berkaitan dengan thread, aku pernah membuat sebuah tool sederhana berbasis Swing untuk generate data yang butuh waktu cukup lama. Secara insting, yang ada dibenakku adalah membuat thread baru untuk proses yang lama tersebut. Tapi ternyata itu belum cukup, selama proses, tampilan GUI menjadi tidak responsif dan output diagnosa ke text area setiap item selesai diproses tidak muncul seperti yang aku harapkan.

Untuk mengatasi masalah ini, aku perlu mempelajari konsep threading di Swing. Ada tiga jenis thread disini, yaitu initial thread, event dispatch thread, dan worker thread (background thread). Initial thread adalah thread dimana aplikasi bermula, atau thread yang menjalankan method main. Event disptach thread adalah thread yang bertugas untuk menangani event-handling. Seluruh method milik komponen Swing yang tidak thread safe harus dijalankan di thread ini. Oleh sebab itu, umumnya initial thread akan mengerjakan SwingUtilities.invokeLater atau SwingUtilities.invokeAndWait, agar kode yang membentuk GUI (membuat frame, mengisi layout, dsb) berjalan di event dispatch thread. Contohnya adalah seperti:

public static void main (String args[]) {
  SwingUtilities.invokeLater(new Runnable() {
    public void run() {
      createAndShowGUI();
    }
  });
}
    

Untuk kode yang melakukan proses jangka panjang, aku harus mengerjakannya di worker thread. Jika dilakukan di event dispatch thread, maka GUI yang menjadi tidak responsif dan tidak sempat lagi menangangi event (karena sibuk mengerjakan proses jangka panjang tadi). Agar proses dikerjakan oleh worker thread, aku dapat menggunakan SwingWorker (baru di Java 6). Berikut ini adalah contohnya:

protected class TaskBerat extends SwingWorker<Void, Integer> {

  @Override
  protected Void doInBackground() throws Exception {
    for (int i=0; i<100; i++) {
      publish(i);
      Thread.sleep(100);
    }
    return null;
  }

  @Override
  protected void process(List<Integer> chunks) {
    for (Integer i : chunks) {
      txtOutput.append("Processing task #" + i + "\n");
    }
  }
}
    

Method doInBackground() akan dikerjakan oleh worker thread, sementara method process() akan dikerjakan oleh event dispatch thread. Aku menggunakan publish() di doInBackground() untuk mengirim nilai ke process(). Demi alasan performance, sekali pemanggilan process() mungkin akan melayani lebih dari satu publish(), dimana nilai yang di-publish disimpan dalam sebuah List. Karena process() dijalankan oleh event dispatch thread, aku bebas mengerjakan method milik Swing disini (sebenarnya method append() milik JTextArea termasuk thread-safe).

Satu lagi class yang berhubungan thread di Swing adalah class javax.swing.Timer. Perbedaannya dengan class java.util.Timer adalah Swing Timer dikerjakan oleh event dispatch thread, sehingga aman untuk memakai method milik komponen Swing di Swing Timer. Berikut ini contoh program yang menampilkan waktu saat ini:

public class LatihanTimer extends JFrame implements ActionListener {

  private JLabel lblWaktu;
	
  public LatihanTimer() {
   super("Latihan Timer");
		
   lblWaktu = new JLabel("[WAKTU]");
   add(lblWaktu);
   pack();
   setVisible(true);
		
   Timer timer = new Timer(1000, this);
   timer.start();
  }
	
  public static void main (String args[]) {
   SwingUtilities.invokeLater(new Runnable(){
		
     @Override
     public void run() {
       new LatihanTimer();
     }
			
   });
  }

  @Override
  public void actionPerformed(ActionEvent e) {
   lblWaktu.setText(DateFormat.getTimeInstance().format(new Date()));
  }
}

Perihal Solid Snake
I'm nothing...

Apa komentar Anda?

Please log in using one of these methods to post your comment:

Logo WordPress.com

You are commenting using your WordPress.com account. Logout / Ubah )

Gambar Twitter

You are commenting using your Twitter account. Logout / Ubah )

Foto Facebook

You are commenting using your Facebook account. Logout / Ubah )

Foto Google+

You are commenting using your Google+ account. Logout / Ubah )

Connecting to %s

%d blogger menyukai ini: