Lebih Dekat Dengan Class SwingWorker

Beberapa minggu terakhir ini, saya mendapatkan 2 pertanyaan tentang Bagaimana sih agar progress bar bisa berjalan pada saat proses Query ? dan Bagaimana sih cara membuat sebuah login dialog yang menampilkan progress bar ? Nah karena 2 pertanyaan tersebut saling berkaitan menurut saya (sama-sama ingin menjalankan Progress Bar pada saat aplikasi sedang menjalankan tugas/proses yang lain) maka akan saya jawab bersama-sama pada tulisan ini :) . Nah sebelum kita masuk ke penjelasan lebih detail, kita harus tahu dahulu dong kenapa kita tidak bisa secara langsung menjalankan progress bar di saat kita melakukan proses yang lain ? Ada yang tahu kenapa ? Ini karena semua “Event Handling” yang terdapat pada Java Swing dijalankan oleh Thread yang bernama Event Dispatch Thread (EDT) Waks.. Thread ? Yaps betul Thread :)

Agar aplikasi yang kita bangun di Java Swing tidak terlihat nge-“freeze” (tidak responsif/nge-hang), maka kita juga perlu tahu beberapa Thread yang terdapat di Java Swing. Thread-thread tersebut yaitu :

  1. Initial Thread
    Thread ini bertugas untuk menjalankan method main dari aplikasi Swing kita dan thread ini bertugas untuk menampilkan GUI (Graphical User Interface) yang sudah kita bangun diatas Swing ke layar. Setelah GUI (Graphical User Interface) tampil, maka kerja dari thread ini telah selesai dan akan dilanjutkan oleh Event Dispatch Thread.
  2. Event Dispatch Thread
    Setiap aplikasi berbasis Java Swing hanya dapat mempunyai 1 Event Dispacth Thread (EDT) saja. Setiap respon dari penekanan tombol, menu item, update tampilan komponen akan dijalankan oleh thread ini. Dan semua proses tersebut biasanya tidak membutuhkan waktu yang lama. Jadi, segala proses yang dijalankan pada thread ini harus selesai secepat mungkin agar aplikasi kita tidak terlihat nge-“freeze” (tidak responsif/nge-hang) .
  3. Worker Thread
    Worker thread atau biasanya disebut dengan background thread ini berfungsi untuk menjalankan proses yang lama seperti pembacaan direktori pada file system atau proses query ke database. Gunakan thread ini untuk melakukan operasi atau proses yang kita tidak bisa menentukan kapan kira-kira proses tersebut selesai.


Nah sekarang yang jadi pertanyaan yaitu apa hubungan-nya antara thread-thread diatas dengan class SwingWorker ? Ok untuk menjawab pertanyaan ini sekarang buatlah sebuah project di NetBeans IDE, kemudian buatlah sebuah JFrame dan design-lah JFrame tersebut seperti gambar dibawah ini :
DesignFrame
Design JFrame

Kemudian pada tombol Tampilkan Angka tambahkan kode seperti dibawah ini :

Setelah selesai, sekarang coba jalankan aplikasi-nya kemudian tekanlah tombol Tampilkan Angka dan jika tidak ada kesalahan maka kita akan mendapatkan tampilan seperti 2 gambar dibawah ini:

FreezeFrame
Tampilan Frame Nge-Freeze
AfterProses
Setelah Proses Looping

Pada tampilan diatas, kita bisa melihat bahwa GUI (Graphical User Interface) kita seakan-akan nge-freeze beberapa detik baru kemudian normal kembali dengan tiba-tiba menampilkan angka pada JTextArea. Hmmm koq aneh, padahal yang kita inginkan yaitu ketika proses perulangan berlangsung progress bar-nya berjalan dan angka akan ditampilkan satu persatu pada text area. Kenapa bisa seperti itu ?? Jawaban-nya adalah, karena kita melakukan proses perulangan dan meng-update tampilan (GUI) di dalam 1 thread yaitu Event Dispatch Thread (EDT). Sedangkan proses diatas, dapat kita gambarkan sebagai berikut :
flow_EDT
Flow EDT Ketika Penekanan Tombol, EDT Tidak Bisa Mengupdate Komponen

Note: Gambar diambil dan dimodifikasi dari http://java.sun.com/developer/technicalArticles/javase/swingworker/

Dari gambar flow EDT diatas, pada titik A itulah saat kita melakukan proses penekanan tombol Tampilkan Angka. Nah selama proses perulangan kita juga ingin meng-update tampilan dengan menampilkan angka satu persatu ke text area. Karena proses perulangan belum selesai, maka intruksi jTextArea1.append(“Angka ke ” + i + “\n”); ini tidak dapat dilakukan. Intruksi jTextArea1.append(“Angka ke ” + i + “\n”); ini baru berjalan ketika EDT sudah mencapai pada titik B.

Nah sekarang bagaimana caranya agar ketika kita melakukan per-ulangan, tampilan pada GUI juga ikut terupdate ? Solusi-nya yaitu dengan menggunakan Background Thread atau pada thread yang terpisah dari Event Dispatch Thread (EDT). Tujuan ini yaitu agar Event Dispatch Thread (EDT) dapat terus mengupdate GUI. Dan proses menjalankan Background Thread tersebut dapat kita jalankan ketika Event Dispatch Thread (EDT) berada pada Titik A atau ketika kita menekan tombol Tampilkan Angka. Dan proses ini dapat kita gambarkan seperti dibawah ini :
twothreads
Memisahkan EDT dengan Menggunakan Background Thread

Note: Gambar diambil dan dimodifikasi dari http://java.sun.com/developer/technicalArticles/javase/swingworker/

Mengenal SwingWorker Sebagai Solusi Background Thread

Untuk membuat sebuah Background Thread menggunakan class SwingWorker caranya sangat sederhana sekali yaitu buatlah sebuah class yang meng-extends class SwingWorker dan override-lah 1 buah method yaitu method doInBackground() seperti dibawah ini :

Dimana T merupakan return type dari method doInBackground dan V adalah tipe yang akan digunakan oleh method publish dan process jika kita menggunakan method tersebut pada Background Thread kita. Sedangkan pada SwingWorker sendiri terdapat 3 thread yang mempengaruhi siklus kehidupan dari SwingWorker yaitu :

  • Current Thread
    Method SwingWorker.execute dipanggil dari thread ini. Thread ini mempunyai tugas untuk menjalankan “Worker Thread” saja.
  • Worker Thread
    Method SwingWorker.doInBackground ini dipanggil dari thread ini. Dan disini seharusnya semua Background Process dilakukan.
  • 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()

Sedangkan untuk penggunaan standart-nya, kita sebenarnya hanya perlu meng-override method doInBackground saja. Dan jika proses yang dikerjakan oleh method doInBackground telah selesai maka method SwingWorker.done() akan dijalankan :)

Implementasi SwingWorker

Nah sekarang setelah mengetahui Basic Thread di Java Swing dan sedikit mengenal tentang SwingWorker terus sekarang bagaimana cara penggunaan-nya ? Sama seperti diatas, cara penggunaan-nya sangat sederhana sekali. Kopi-lah dahulu latihan pertama yang sudah kita buat di-awal kemudian gantilah nama filenya dengan WithBackgroundThread.java kemudian tambahkan-lah sebuah private class dengan nama WorkerLookup seperti dibawah ini :

Penjelasan kode diatas yaitu :

  • Pada baris 102, kita membuat sebuah class dengan nama WorkerLoop yang meng-extends SwingWorker dengan parameter . Dimana String ini digunakan untuk menjelaskan tipe data apa yang akan dikembalikan oleh method doInBackground, karena pada class WorkerLoop ini tidak meng-override method proces maka kita bisa menggunakan tipe Void saja :)
  • Pada baris 120 inilah proses yang dijalankan pada Background Thread dilakukan, dan setelah method doInBackground ini selesai dijalankan maka kita akan mengirimkan pesan bertipe String ke method done()
  • Pada baris 105-117 ini kita gunakan untuk mengupdate GUI yang menandakan bahwa Background Process telah selesai dilakukan, dan kita dapat mengambil nilai yang dikirmkan oleh method doInBackground dengan menggunakan method get().

Setelah pembuatan WorkerLoop selesai, sekarang deklarasikan class WorkerLoop tersebut seperti dibawah ini:

Kemudian langkah terakhir yaitu editlah kode yang terdapat pada tombol Tampilkan Angka hingga menjadi seperti dibawah ini :

Sekarang coba jalankan dan tekanlah tombol Tampilkan Angka, seharusnya sekarang GUI kita sudah tidak nge-freeze ketika sedang melakukan perulangan dan progress bar-nya pun sudah bisa jalan dengan baik :) Mudah bukan ? Tapi yang perlu kita perhatikan ketika membangun aplikasi yang menggunakan Thread yaitu adalah berhati-hatilah dalam menggunakan-nya, karena sekali saja aplikasi terjadi kesalahan maka proses debugging-nya susah sekali :D

Dan dibawah ini adalah halaman-halaman referensi yang saya gunakan dan mohon maaf kalau ada salah kata/penyampaian :) :D
Link-link terkait :
- SwingWorker API JDK 1.6
- Penjelasan Tentang SwingWorker (WIKI)
-
Penjelasan Tentang EDT (WIKI)
-
Tutorial Concurrency di Java Swing
- Improve Application Performance With SwingWorker in Java SE 6
- Penjelasan Tentang Thread (WIKI)
- Milis NetBeans Indonesia
- Sample Project
- SubVersion Mudah Dengan RabbitVCS

Tags:

18 Responses to “Lebih Dekat Dengan Class SwingWorker”

  1. Rapi sekali, Pak Mar! Apa tip untuk membuat tulisan berkode sehingga bisa serapi ini? Bisakah bapak tuliskan tutorialnya khusus?

  2. gugum web says:

    Karena dari Oracle Documentation ketikannya ada yg salah
    http://docs.oracle.com/javase/tutorial/uiswing/concurrency/simple.html

    jujur, ak masih bingung kapan pake doInBackground() aja ama kapan aku harus nulis di done() method.
    Anyway, klo bs kasi ak masukan, let me know ya?
    blm kejawab juga nih….

    • @gugum: Btw bisa kasih tahu, ketikan yg salah di dokumentasi-nya Oracle bagian mana ya ? Saya lihat koq keknya ga ada yg salah ?? (Apa saya yg kurang jeli ya ?)

      Penggunaan method doInBackground() ini HARUS dilakukan jika kita meng-extends class SwingWorker karena pada method ini-lah sebuah proses akan dijalankan pada Thread yang terpisah dari EDT. Sedangkan untuk penggunaan method done() ini optional bisa kita pakai, bisa juga tidak.
      Nah terus kapan kita harus nulis sesuatu di method done() ? Jika kita ingin menerima hasil dari proses yang dikerjakan di dalam method doInBackground maka satu-satunya cara untuk mengambil hasil-nya terdapat pada method done().

      Gimana ? Masih kurang jelas juga ? Jika masih bingung, coba dulu contoh project-nya dan coba jalankan. Kalau perlu, sekalian debug di NetBeans, trace line by line lewat NetBeans IDE supaya lebih mudah memahami alur logika-nya :)

  3. Enden Muhaemin says:

    gan.. bisa sher contoh program yang bisa nampilin format pdf .
    dan tampil di form nya

Leave a Reply

[+] adsenseid emoticons by Martinus Ady H. Modified from nartzco source code.