Implementasi SwingWorker pada Java Swing


Ketika kita mendesain suatu aplikasi dengan Java Swing, ada kalanya kita ingin melakukan proses yang cukup memakan resource dan waktu, yang kadang menyebabkan ada suatu proses yang tidak bisa dieksekusi ketika aplikasi sedang menjalankan proses yang lain. Mengapa hal tersebut bisa terjadi? Hal ini dikarenakan adanya suatu event handling yang dijalankan oleh Thread yang bernama Event Dispatch Thread (EDT). Umumnya semua kode atau proses yang memanggil method yang terdapat pada Java Swing juga dikelola oleh EDT. EDT juga dibutuhkan mengingat banyak method Swing yang “not thread safe” yang berpengaruh ke konsistensi dari memory yang ada. Selain itu akan muncul suatu problem baru ketika kita melibatkan suatu proses yang memakan waktu cukup lama ke dalam Swing dimana aplikasi kita tidak responsif yang ditandai dengan freeze/hang ketika melakukan proses yang cukup panjang. Oleh karena itu mari kita perlu mengetahui beberapa Thread yang digunakan pada Java Swing.

Initial Thread

Thread ini  berfungsi untuk membuat Runnable object yang dapat menginisialisasi GUI,  melakukan schedule, dan meneruskan ke Event dispatch Thread. Artinya ketika kita membuat method main, maka Thread ini akan menginisialisasi GUI dan menampilkannya kemudian diteruskan ke EDT

Event Dispatch Thread

Seperti keterangan sebelumnya, semua proses yang melibatkan Swing dikerjakan oleh Thread ini, seperti proses ketika menekan tombol atau melakukan update item dalam suatu komponen. Hal tersebut berarti setiap aplikasi Java Swing hanya mempunyai satu EDT saja, sehingga ketika menjalankan suatu proses harus dapat diprediksi dan diselesaikan dengan cepat untuk menjaga agar aplikasi tetap responsif

Worker Thread (Background Thread)

Thread ini digunakan untuk menjalankan proses yang cukup lama, seperti melakukan query dari database, membaca/menulis file ke direktori tertentu. Nah thread inilah yang perlu kita gunakan ketika kita melibatkan suatu proses yang cukup besar atau ketika kita tidak dapat memprediksi kapan proses tersebut akan selesai.

Setelah teman-teman berkenalan dengan thread di Java Swing, saya akan membuat sebuah contoh untuk ilustrasi penggunaan SwingWorker pada Java Swing, tujuannya agar kita dapat menjalankan proses secara bersamaan dan aplikasi tetap responsif ketika menjalankan proses yang cukup besar. Kita buat suatu frame yang didalamnya menjalankan proses menampilkan angka dari 1 hingga 10.000, selama proses tersebut akan muncul progress bar, ketika proses selesai maka progres bar akan berhenti. Ilustrasi nya kurang lebih seperti ini

Untuk method pada tombol Mulai kurang lebih seperti ini

<br />private void buttonCountActionPerformed(java.awt.event.ActionEvent evt)<br /><%%KEEPWHITESPACE%%> {<br /><%%KEEPWHITESPACE%%>   // bersihkan textarea<br /><%%KEEPWHITESPACE%%>   textArea.setText("");<br /><%%KEEPWHITESPACE%%>   // mulai progress<br /><%%KEEPWHITESPACE%%>   progress.setIndeterminate(true);<br /><%%KEEPWHITESPACE%%>   // mulai count dan tampilkan ke dalam teks area<br /><%%KEEPWHITESPACE%%>   for(int i=0;i&lt;10000;i++)<br /><%%KEEPWHITESPACE%%>   {<br /><%%KEEPWHITESPACE%%>     textArea.append("Angka ke - "+ i +" n");<br /><%%KEEPWHITESPACE%%>   }<br /><%%KEEPWHITESPACE%%>   // selesai progress<br /><%%KEEPWHITESPACE%%>   progress.setIndeterminate(false);<br /><%%KEEPWHITESPACE%%>   textArea.append("nSelesai");<br /><%%KEEPWHITESPACE%%> }<br /><br />

Ketika kita jalankan frame tersebut, ternyata aplikasi tersebut freeze/hang, selain itu progress bar yang kita harapkan untuk berjalan ternyata tidak terlihat. Mengapa hal tersebut terjadi? Alasannya adalah karena kita melakukan proses perulangan dan mengupdate GUI dalam satu thread yaitu di Event Dispatch Thread, kira-kira kalau diilustrasikan seperti ini

Point A adalah saat kita melakukan proses perulangan angka. Selain itu pada proses tersebut kita juga ingin melakukan update tampilan dengan menampilkan angka hasil perulangan kedalam teks area. Kareana proses perulangaan belum selesai, maka perintah textArea.append(..) tidak dapat dilakukan, perintah tersebut baru dieksekusi ketika proses perulangan telah selesai atau berada pada point B. ilustrasi diatas menunjukkan ada jeda yang cukup panjang yang menjadi penyebab mengapa aplikasi kita kurang responsif.

Nah, bagaimana mengatasi permasalahan tersebut? Solusinya kita menggunakan Worker thread yang terpisah dari EDT. Tujuannya agar EDT dapat melakukan update GUI secara bersamaan dengan kita melakukan proses perulangan. Proses nya dimulai saat kita memerintahkan untuk menampilkan angka. Skema yang kita harapkan kurang lebih menjadi seperti ini

Membuat class SwingWorker

Pertama-tama kita buat kelas yang mengekstend class SwingWorker, dimana class ini memiliki 2 parameter <T,V>

T –  tipe data hasil yang dikembalikan oleh method doInBackground dan get

V-  tipe data yang digunakan method  publish and process jika kita menggunakannya ke dalam background thread

SwingWorker sendiri terdapat 3 thread yang mempengaruhi siklus kehidupan dari SwingWorker yaitu :

 1. Current Thread

Method SwingWorker.execute() dipanggil dari thread ini. Thread ini mempunyai tugas untuk menjalankan “Worker Thread” saja.

2. Worker Thread

Method SwingWorker.doInBackground() ini dipanggil dari thread ini. Dan disini seharusnya semua Background Process dilakukan.

3. Event Dispatch Thread

Semua aktifitas yang berkaitan dengan Java Swing dilakukan pada thread ini, thread ini juga akan memanggil method SwingWorker.done() dan SwingWorker.process()

Implementasi SwingWorker

Setelah teman-teman dijejali 😀 tentang teori SwingWorker, saat nya kita mencoba mengimplementasikan ke dalam source code kita. Pertama-tama kita buat private class didalam source kita tadi, kira-kira seperti ini.

<br />private class WorkerThread extends SwingWorker&lt;String, Void&gt;<br />{<br /><%%KEEPWHITESPACE%%> @Override<br /><%%KEEPWHITESPACE%%> protected String doInBackground() throws Exception<br /><%%KEEPWHITESPACE%%> {<br /><%%KEEPWHITESPACE%%>   for (int i = 1; i &lt;= 10000; i++)<br /><%%KEEPWHITESPACE%%>   {<br /><%%KEEPWHITESPACE%%>    textArea.append("Angka ke - " + i + " n");<br /><%%KEEPWHITESPACE%%>   }<br /><%%KEEPWHITESPACE%%>   return "nSelesai";<br /><%%KEEPWHITESPACE%%> }<br /><br /><%%KEEPWHITESPACE%%> @Override<br /><%%KEEPWHITESPACE%%> protected void done()<br /><%%KEEPWHITESPACE%%> {<br /><%%KEEPWHITESPACE%%>   try {<br /><%%KEEPWHITESPACE%%>    if (get() != null)<br /><%%KEEPWHITESPACE%%>    {<br /><%%KEEPWHITESPACE%%>     textArea.append(get());<br /><%%KEEPWHITESPACE%%>    }<br /><%%KEEPWHITESPACE%%>    progress.setIndeterminate(false);<br /><%%KEEPWHITESPACE%%>   }<br /><%%KEEPWHITESPACE%%>   catch (InterruptedException ex) {<br /><%%KEEPWHITESPACE%%>    Logger.getLogger(SwingWorkerExample.class.getName())<br /><%%KEEPWHITESPACE%%>    .log(Level.SEVERE, null, ex);<br /><%%KEEPWHITESPACE%%>    } catch (ExecutionException ex) {<br /><%%KEEPWHITESPACE%%>     Logger.getLogger(SwingWorkerExample.class.getName())<br /><%%KEEPWHITESPACE%%>     .log(Level.SEVERE, null, ex);<br /><%%KEEPWHITESPACE%%>   }<br /><%%KEEPWHITESPACE%%>  }<br /><%%KEEPWHITESPACE%%> }<br /><br />

Pada class yang kita buat menggunakan parameter <String,Void>, dimana String merupakan tipe data yang dipakai dan dikembalikan pada method doInBackground() sedangkan Void digunakan karena kita tidak melakukan override terhadap method process(). Nilai yang dikembalikan oleh method doInBackground dapat kita akses melalaui method get().

Setelah class tersebut dibuat maka kita dapat melakukan modifikasi pada tombol aksi menjadi seperti ini

<br /><br />private void buttonCountActionPerformed(java.awt.event.ActionEvent evt)<br /><%%KEEPWHITESPACE%%> {<br /><%%KEEPWHITESPACE%%>  // bersihkan textarea<br /><%%KEEPWHITESPACE%%>  textArea.setText("");<br /><%%KEEPWHITESPACE%%>  // mulai progress<br /><%%KEEPWHITESPACE%%>  progress.setIndeterminate(true);<br /><%%KEEPWHITESPACE%%>  // jalankan SwingWorker<br /><%%KEEPWHITESPACE%%>  new WorkerThread().execute();<br /><%%KEEPWHITESPACE%%> }<br /><br />

Hasilnya aplikasi kita dapat menampilkan angka 1 hingga 10.000 dan selama proses tersebut ditampilkan progress bar. Nah semoga dengan uraian yang cukup panjang ini mampu membuat teman-teman semakin memahami penggunaan SwingWorker pada Java Swing, yang jelas pahami konsep dengan baik karena jika sudah berurusan dengan Thread rada susah buat debugging nya 😛 Jika teman-teman membutuhkan contoh source untuk latihan ini, dapat diunduh di Dropbox

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s