19 เมษายน 2553

java swingworker multithread programming tutorial

java swingworker multithread programming tutorial

SwingWorker is one of the most handiest utility classes provided in Swing. Most of the interviews on Swing have a question or two on this class. Let’s make sure you know all about it’s need and usage. Step by Step.
A (Quick) look at the problem with the “Event Dispatch” thread:

The “Event Dispatch” Thread(EDT) is a special thread in Swing where all graphical events are processed. One such event is painting the screen. Also, all the listeners attached to swing components are executed in the EDT(BTW, make it an habit to call it the “EDT”, it looks cool on interviews).

So, get this clear, the code that paints the screen and your code that executes inside a listener, both runs on the EDT. Now, by the laws of nature, within a “single” thread operations cannot execute parallely. So when your listener code is executing, the code that paints the screen cannot execute. clear? If not read the above line again.

Now, If your listener code takes a long time to execute(for eg., fetching large data from the network), till it’s completion the screen wouldn’t get painted. This makes the application look as if it’s hung. (You should have definitely seen this in almost all Java IDES.

If you’ve not paid attention, Wait for the time when you JAVA IDE seems to be hung,

then change the window and then come back to the IDE window. you won’t see anything on the screen, just the blank form. that’s what I am talking about)
Ok, how do I un-hang my Swing Application

Simple. Don’t let the code in your listener execute for a long time. But what if you have to write code that takes long time to execute? For eg., what if you need to fetch large data from a db table and display it to the user when the user presses a button? Again, Simple. Execute the time consuming task in a separate thread. The paint method executing in the EDT can execute parallely when your new thread is happily waiting for the data to get fetched from the DB(yes, the laws of nature allow this). Simple, right?
But wait, it’s not that simple. What would you do after you fetch the data. You cannot display the value directly from the new thread that you just created! As I told you all graphical operations must execute in the EDT. So you need to come back to the even dispatch thread to display the fetched values…How do you do that? I will come to that in a second. but let’s make sure you have the steps clearly defined.
So here are the steps,

-The action listener(of the button press) gets executed in the EDT

-You make a background thread to load the data [or does any other time consuming task for that matter]

-the background task calls code in the EDT to display the newly fetched data.
From the background thread you can use methods like SwingUtilties.invokeLater() to run code in the EDT.. But….
Wouldn’t it be dreamy if …(yes, this title was picked up those head first books)
Wouldn’t it be dreamy you could write just two methods, one method (m1) where you put the code to load data and the other method (m2) where you write the code to update the UI? Wouldn’t it be great, if automatically m1(loading the data) is called first and then when that completes,m2 is automatically called? Wouldn’t it be magical, if somehow m1 could be automatically get called in a background thread and m2 in the EDT?

Well, lucky you, there’s a simple utility class ships with Java 6 that let’s you do this. and that class is… well, no surprise here.. The SwingWorker Class.

So SwingWorker is this..
A class having two main methods,
-method “doInBackground()” which always get executed in the background thread. This is the m1 method we were discussing in the last paragraph. Here you can put code that executes for as much time as you like!

-method “done()” which always gets executed in the EDT, and always get executed after the doInBackground() method gets finished. Same as the m2 method in the previous paragraph. So here’s where you put the code that displays the data after the data gets loaded.



An Example
SwingWorker worker = new SwingWorker() {
//This method automatically gets executed in a background thread

public List doInBackground() {

//fetch the big list from the

List list = getBigListAfterExecutingForLongTime();

return intDoc;

}
//This methods automatically gets executed in the EDT

public void done() {

//Get method retuns the exect, same thing

//that the doInBackground() method returned

List list = get();
//Now do all UI Operations here..

updateTheUIWithThisBigList(list);

}

};
//Code that executes when the button is pressed

public void actionPerformed(ActionEvent ae){

worker.execute();

}

from http://www.indijava.in/community/tutorial/Using-SwingWorker-A-Step-by-Step-tutorial



1 ความคิดเห็น:

บทความยอดนิยม (ล่าสุด)

บทความยอดนิยม (All Time)