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
Multiple threads accessing shared data simultaneously may lead to a timing dependent error known as data race condition. Data races may be hidden in the code without interfering or harming the program execution until the moment when threads are scheduled in a scenario (the condition) that break the program execution.
Multiple threads can also read data from the same FITS file simultaneously, as long as the file was opened independently by each thread. This relies on the operating system to correctly deal with reading the same file by multiple processes.
The definition of a deadlock is when two or more threads cannot complete their execution because they are mutually blocked and waiting for something from the other thread(s).
Apparently, SwingWorker
s 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 actionPerformed
s, execute your SwingWorker
s like this
executor.execute(new Main.MyTask("First"));
This will execute each SwingWorker on a separate thread in a Thread pool.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With