Hi All,

I am learning Multithreading in Java and came across this code using SwingWorker for GUI multithreading.
Here is the modified code done by me.

import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.List;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingWorker;

public class MainFrame extends JFrame {
private JLabel countLabel1 = new JLabel("0");
private JLabel statusLabel = new JLabel("Task not completed.");
private JButton startButton = new JButton("Start");

public MainFrame(String title) {
super(title);

setLayout(new GridBagLayout());

GridBagConstraints gc = new GridBagConstraints();

gc.fill = GridBagConstraints.NONE;

gc.gridx = 0;
gc.gridy = 0;
gc.weightx = 1;
gc.weighty = 1;
add(countLabel1, gc);

gc.gridx = 0;
gc.gridy = 1;
gc.weightx = 1;
gc.weighty = 1;
add(statusLabel, gc);

gc.gridx = 0;
gc.gridy = 2;
gc.weightx = 1;
gc.weighty = 1;
add(startButton, gc);

Thread t4 = new Thread(new Runnable(){
    public void run(){
startButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
start();
}
});
    }});        
t4.start();
setSize(200, 400);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setVisible(true);
}


private void start() {

SwingWorker<Boolean, Integer> worker = new SwingWorker<Boolean, Integer>() {

@Override
protected Boolean doInBackground() {
Thread t1 = new Thread(new Runnable(){

    @Override
    public void run() {
        for(int i=0; i<30; i++) {
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                System.out.println("Interrupted");
                e.printStackTrace();
            }
            System.out.println("Hello: " + i);
            publish(i);
        }
    }

});
t1.start();


return false;
}

@Override
protected void process(final List<Integer> chunks) {
Thread t2 = new Thread(new Runnable() {

    @Override
    public void run() {
        Integer value = chunks.get(chunks.size() - 1);

        countLabel1.setText("Current value: " + value);

    }
});
t2.start();
}

@Override
protected void done() {

try {
Boolean status = get();
statusLabel.setText("Completed with status: " + status);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}

};

worker.execute();
}
}

And this is the class containing main method

import javax.swing.SwingUtilities;


public class App{
    public static void main(String[] args){
        SwingUtilities.invokeLater(new Runnable(){

            @Override
            public void run() {
                new MainFrame("SwingWorker Demo");

            }

        });
    }
}

What i am unable to understand is even though i am running the processes in different threads(t1,t2 and t4) when i close the JFrame window, the console window will also stop printing "Hello". Why is this happening since threads are meant for parallel processing and i am running them in seperate threads...If i want to continue printing "Hello" in console even after JFrame is closed,how do i do it using threads?
Thanks in advance.

Recommended Answers

All 5 Replies

You coded
54. setDefaultCloseOperation(EXIT_ON_CLOSE);
and Java is doing what you told it! That option instructs Java to exit the whole program when the JFrame is closed.

I realise that you are practicing with Threads here, but t4 just executes an addActionListener, which isn't enough for you to be able to observe any multi-threaded behaviour.
Also t1 and t2 are missing the whole point of SwingWorker, because Swing runs the doInBackground and process methods in suitable Threads anyway. Indeed by using your own thread for the process method you are breaking the program - process is where you updade the GUI so it MUST be executed on the Swing EDT thread (which is where SwingWorker calls it)

Thanks for your answer JamesCherrill. If i want to continue printing "Hello" in console even after JFrame is closed,how do i do it using threads? Is there any way ? Which option should i choose for closing operation of JFrame ?

  1. To prevent the application for terminating when yuo close the window, use WindowConstants.DISPOSE_ON_CLOSE (releases all the window's resources, leaves the program running) or WindowConstants.HIDE_ON_CLOSE (just makes the window invisible).

  2. For your Thread exercise I suggest you forget SwingWorker for the moment. SwingWorker does all the thread-related stuff for you, so it's not helpful for learning.
    All you need to do is to call invokeLater (ie what you do now) to run the method that will create the window on the Swing EDT thread - no other threads should be involved in that. Then create and start an ordinary thread that prints to the console in a loop. You may want to think about how to terminate that loop...

If after that you want to have some kind of interaction between the console loop and the window, that gets a bit more tedious, and you start to see why SwingWorker was invented.

That helped a lot JamesCherrill. Thank you..:)

  • setProcess, publish, process aren designated to be right place for creating another thread, they are connectors to EDT

  • SwingWorker is single threaded, isn't reusable, can't returns any states about itself, designated as bridge betweens EDT and Workers Threads, everything should be executed/initalized/e.i. inside doInBackground(), rest of methods are designated to be an output from doInBackground(), done() is end_of_single instance, a few (non_important events) can be listened by PropertyChangeListener,

  • isn't designated for Multithreading (link in the next point), is possible by invoke from Executor, but why to add another black hole to SwingWorker and Future, there isn't any control over the process from SwingWorker and Future, note thread must be named as local variable - constans in SwingWorker, otherwise there isn't another reference to use cancel(), Executor and SwingWorker has a few bugs in Oracles bugparade

  • get() inside done() is for testing if is there any exception, otherwise isn't possible to catch any exception,

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.