SwingWorker in Java

SwingWorker is an abstract class developed for Swing library of the Java programming language. It is used to performed lengthy GUI interaction tasks in a background thread. While developing applications, sometimes the GUI hangs when it is trying to do some huge or lengthy task. This lag is a big bottleneck. For such purposes, swingworker is developed which schedules the execution of this lengthy task on a different thread while the GUI still remains responsive.

Java language has three threads, namely:

  • Current Thread (Initial Thread): this is the thread on which the initial application logic executes.
  • Event Dispatch Thread: all event handling code executes on this thread.
  • Worker Threads: also known as background thread where all time consuming background tasks are executed.

SwingWorker allows user to schedule the execution of background task on Worker Thread. But how will the user get to know when the task as finished its execution or if user needs to update GUI(running on initial thread) as per the thread execution? This implies we need inter-thread communication as well. SwingWorker is designed for such tricky situations which provides communication on event dispatch thread.



Important methods of SwingWorker:

  1. doInBackground(): This function contains our logic of the background task i.e. what we want our thread to do. This function runs on worker thread and is necessary to implement.
    protected abstract T doInBackground()
                                 throws Exception
    Computes a result, or throws an exception if unable to do so. 
    This method is executed in a background thread.
    Returns:
    the computed result
    Throws:
    Exception - if unable to compute a result
  2. done(): This function is called when the thread finished its execution. Also, any value returned by the doInBackground() function can be received inside this function using get(). Further, updates can be made to GUI inside this function. Thus, function executes on the Event Dispatch Thread after the doInBackground method is finished.
    protected void done()
  3. execute(): Schedules this SwingWorker for execution on a worker thread.
    public final void execute()
  4. publish() : This method is to be used from inside the doInBackground method to deliver intermediate results for processing on the Event Dispatch Thread inside the process method.
    protected final void publish(V... chunks)
  5. process(): Receives data chunks from the publish method asynchronously on the Event Dispatch Thread. Because this method is invoked asynchronously, publish() may have been called multiple times.
    protected void process(List chunks)
    Parameters:
    chunks - intermediate results to process
  6. run(): Sets this Future to the result of computation unless it has been cancelled.
    public final void run()
  7. setProgress: Sets the progress bound property. The value should be from 0 to 100.
    protected final void setProgress(int progress)
    
    Example:
    setProgress(1);
    setProgress(2);
    setProgress(3);
     
    might result in a single PropertyChangeListener 
    notification with the value 3.
    Parameters:
    progress - the progress value to set
    Throws:
    IllegalArgumentException - is value not from 0 to 100
  8. getProgress: Returns the progress bound property.
    public final int getProgress()
    Returns:
    the progress bound property.
  9. cancel: Attempts to cancel execution of this task. This attempt will fail if the task has already completed, has already been cancelled, or could not be cancelled for some other reason. If successful, and this task has not started when cancel is called, this task should never run. If the task has already started, then the mayInterruptIfRunning parameter determines whether the thread executing this task should be interrupted in an attempt to stop the task.
    After this method returns, subsequent calls to Future.isDone() will always return true. Subsequent calls to Future.isCancelled() will always return true if this method returned true.

    public final boolean cancel(boolean mayInterruptIfRunning)
    Parameters:
    mayInterruptIfRunning - true if the thread executing this task 
    should be interrupted; otherwise, in-progress tasks 
    are allowed to complete
    Returns:
    false if the task could not be cancelled, typically 
    because it has already completed normally; true otherwise
  10. isCancelled: Returns true if this task was cancelled before it completed normally.
    public final boolean isCancelled()
    Returns:
    true if this task was cancelled before it completed
  11. isDone: Returns true if this task completed. Completion may be due to normal termination, an exception, or cancellation — in all of these cases, this method will return true.
    public final boolean isDone()
    Returns:
    true if this task completed
  12. get: Waits if necessary for the computation to complete, and then retrieves its result.
    public final T get()
                throws InterruptedException,
                       ExecutionException
  13. getState: Returns the SwingWorker state bound property.
    public final SwingWorker.StateValue getState()
    Returns:
    the current state
    

An example to illustrate SwingWorker

We want or thread to start execution when button is clicked. See startThread() inside button’s action listener. The startThread function defines a new swingworker of the type javax.swing.SwingWorker where,
T – the result type returned by this SwingWorker’s doInBackground and get methods, which is String in below code.
V – the type used for carrying out intermediate results by this SwingWorker’s publish and process methods, which is Integer in below code.

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java program to illustrate 
// working of SwingWorker
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.util.List;
import java.util.concurrent.ExecutionException;
  
import javax.swing.*;
  
  
public class SwingWorkerSample 
{
      
    private static JLabel statusLabel;
    private static JFrame mainFrame;
      
    public static void swingWorkerSample () 
    {
        mainFrame = new JFrame("Swing Worker");
        mainFrame.setSize(400, 400);
        mainFrame.setLayout(new GridLayout(2,1));
          
        mainFrame.addWindowListener(new WindowAdapter() 
        {
  
            @Override
            public void windowClosing(WindowEvent e) 
            {
                System.exit(0);
            }
              
        });
          
        statusLabel = new JLabel("Not Completed", JLabel.CENTER);
        mainFrame.add(statusLabel);
          
        JButton btn = new JButton("Start counter");
        btn.setPreferredSize(new Dimension(5,5));
          
        btn.addActionListener(new ActionListener() 
        {
  
            @Override
            public void actionPerformed(ActionEvent e) 
            {
                System.out.println("Button clicked, thread started");
                startThread(); 
            }
              
        });
          
        mainFrame.add(btn);
        mainFrame.setVisible(true);
    }
      
    private static void startThread() 
    {
  
        SwingWorker sw1 = new SwingWorker() 
        {
  
            @Override
            protected String doInBackground() throws Exception 
            {
                // define what thread will do here
                for ( int i=10; i>=0; i-- ) 
                {
                    Thread.sleep(100);
                    System.out.println("Value in thread : " + i);
                    publish(i);
                }
                  
                String res = "Finished Execution";
                return res;
            }
  
            @Override
            protected void process(List chunks)
            {
                // define what the event dispatch thread 
                // will do with the intermediate results received
                // while the thread is executing
                int val = chunks.get(chunks.size()-1);
                  
                statusLabel.setText(String.valueOf(val));
            }
  
            @Override
            protected void done() 
            {
                // this method is called when the background 
                // thread finishes execution
                try 
                {
                    String statusMsg = get();
                    System.out.println("Inside done function");
                    statusLabel.setText(statusMsg);
                      
                
                catch (InterruptedException e) 
                {
                    e.printStackTrace();
                
                catch (ExecutionException e) 
                {
                    e.printStackTrace();
                }
            }
        };
          
        // executes the swingworker on worker thread
        sw1.execute(); 
    }
      
    public static void main(String[] args) 
    {
        swingWorkerSample();
          
    }
  
}

chevron_right


  1. Run the above code, click the button, you’ll see a counter decrementing. Simultaneously do anything with the UI, it’ll still be responsive.
  2. List chunks is the parameter of process() function and contains the list of every result published by the thread till this time of datatype Integer. The datatype Integer should match with the our swingworker declaration.

Application:
Creating progress bar showing the progress of the task.

References:
Link 1
Link 2

This article is contributed by Ekta Goel. If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.



My Personal Notes arrow_drop_up


Article Tags :
Practice Tags :


1


Please write to us at contribute@geeksforgeeks.org to report any issue with the above content.