views:

164

answers:

1

I have developed a Java Swing application, which uses the SwingWorker class to perform some long running tasks. When the application is run from the IDE (Netbeans), I can start multiple long running tasks simultaneously without any problem.

I created a runnable jar file for the application, in order to be able to run it from outside the IDE. The application when run from this jar file works well with the only exception that it doesn't allow me to start 2 long running tasks simultaneously. The tasks just run one after the other.

I managed to create a very simple program which demonstrates this problem. link The program uses a swingworker which just loops from 1 till 100 and writes the number to the console. The two buttons initiate two threads which do the same thing. If i run this program on netbeans, the threads interleave, while if i create a jar file and run the application from the jar file, the threads do not interleave, but run one after the other.

It seems as if the jvm does not allow more than one thread to run at any one time, when the application is run from the jar file.

Here is the code for those of you having problems with the link

package testingjarpath;

import java.awt.Dimension;
import java.awt.FlowLayout;
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.SwingUtilities;
import javax.swing.SwingWorker;

public class Main extends JFrame
{
    private JButton btnTest;
    private JButton btnTest2;
public Main()
{

this.btnTest = new JButton("Test 1");
this.btnTest.addActionListener(new ActionListener()
{
    public void actionPerformed(ActionEvent e)
    {
    new Main.MyTask("First").execute();
    }
});

this.btnTest2 = new JButton("Test 2");
this.btnTest2.addActionListener(new ActionListener()
{
    public void actionPerformed(ActionEvent e)
    {
    new Main.MyTask("Second").execute();
    }
});

this.setLayout(new FlowLayout());
this.add(this.btnTest);
this.add(this.btnTest2);
this.setSize(new Dimension(400,400));
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this.setVisible(true);
}

public static void main(String[] args) 
{
SwingUtilities.invokeLater(new Runnable()
{
    public void run()
    {
    new Main();
    }
});
}

public class MyTask extends SwingWorker<Void, Integer>
{
private String str;

public MyTask(String str)
{
    this.str = str;
}

@Override
protected Void doInBackground() throws Exception
{
    for(int i = 0; i < 100; i++)
    {
    Thread.sleep(100);
    publish(i);
    }
    return null;
}

protected void process(List<Integer> progress)
{
    System.out.println(str + " " + progress.get(progress.size() - 1));
}

@Override
protected void done()
{
    System.out.println(str + " is ready");
}

}

}

Thanks in advance, Peter Bartolo

+1  A: 

Apparently, SwingWorkers by default all execute on the same background thread in JDK 1.6

Add these

import java.util.concurrent.Executor;
import java.util.concurrent.Executors;

At the top of your Main() add this

final Executor executor = Executors.newCachedThreadPool();

And in your actionPerformeds, execute your SwingWorkers like this

executor.execute(new Main.MyTask("First"));

This will execute each SwingWorker on a separate thread in a Thread pool.

karoberts
A thousand Thanks m8, it works now :)
Spi1988
Glad I could help
karoberts