Open In App

SwingWorker in Java

Improve
Improve
Like Article
Like
Save
Share
Report

SwingWorker is an abstract class developed for the Swing library of the Java programming language. It is used to perform 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 listed below as follows: 

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

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

Important Methods of SwingWorker

Method Action Performed
cancel() Attempts to cancel the execution of this task. This attempt will fail if the task has already been completed, has already been canceled, or could not be canceled 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.

doInBackground() Contains our logic of the background task i.e. what we want our thread to do. It runs on a worker thread and is necessary to implement.
done() It 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.
execute() Schedules this SwingWorker for execution on a worker thread.
getProgress() Returns the progress bound property.
 getState() Returns the SwingWorker state-bound property.
isCancelled() Returns true if this task was canceled before it was completed normally. 
isDone() Returns true if this task is completed. Completion may be due to normal termination, an exception, or cancellation — in all of these cases, this method will return true. 
get() Waits if necessary for the computation to complete, and then retrieves its result.
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.
publish() It is to be used from inside the doInBackground method to deliver intermediate results for processing on the Event Dispatch Thread inside the process method. 
run() Sets this Future to the result of computation unless it has been canceled.
setProgress() Sets the progress bound property. The value should be from 0 to 100. 

Implementation: SwingWorker

We want the thread to start execution when the 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 the below code. 
  • V – the type used for carrying out intermediate results by this SwingWorker’s publish and process methods, which is Integer in the below code.

Example 

Java




// Java Program to Illustrate Working of SwingWorker Class
  
// Importing required classes
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.*;
  
// Main class
// SwingWorkerSample
public class GFG {
  
    private static JLabel statusLabel;
    private static JFrame mainFrame;
  
    // Method
    public static void swingWorkerSample()
    {
        mainFrame = new JFrame("Swing Worker");
        mainFrame.setSize(400, 400);
        mainFrame.setLayout(new GridLayout(2, 1));
  
        mainFrame.addWindowListener(new WindowAdapter() {
            // Method
            @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);
    }
  
    // Method
    private static void startThread()
    {
  
        SwingWorker sw1 = new SwingWorker() {
            // Method
            @Override
            protected String doInBackground()
                throws Exception
            {
  
                // Defining 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;
            }
  
            // Method
            @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));
            }
  
            // Method
            @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();
    }
  
    // Main driver method
    public static void main(String[] args)
    {
        swingWorkerSample();
    }
}


Output:

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

 



Last Updated : 01 May, 2022
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads