I am working on java swing with some multithreaded application. The situation is so, that I need to execute one thread after another i.e I output of one is related to the second. I did the following.
// Class one
public class Samp implements Runnable{
public Samp(String name) {
this.setName = name;
}
public void run (){
// Here I have a file extraction method called
extract(this.getName);
}
// Extract Method
public Boolean extract(String filename){
// Some extraction Operation.
// I want to update the jTextField with the current filename under extraction.
}
}
// the GUI Class
public class Welcome extends javax.swing.JFrame {
SwingWorker<Boolean, Void>worker = new SwingWorker<Boolean, Void>() {
@Override
protected Boolean doInBackground() throws Exception {
Thread t1 = new Thread(new ZipUtility(fileName));
t1.start();
return true;
}
// Can safely update the GUI from this method.
@Override
protected void done() {
// Here when this worker is done I wanted to Run worker 2
}
};
SwingWorker<Boolean, Void>worker2 = .........
// Again when worker2 is done I wanted to run worker 3 and so on.
}
My Questions are :
1) How to run all the workers in a perfect sequencial order. i.e when worker1 is done then start worker 2, when worker2 is done then start worker 3 and so on.
2) How to update a textfield in my Welcome class, with the values from the Samp class.
Thanks in advance.
1) How to run all the workers in a perfect sequencial order. i.e when worker1 is done then start worker 2, when worker2 is done then start worker 3 and so on.
A little trick to remember, you can put a SwingWorker
into a ExecutorService
So, using something like...
public static class Worker extends SwingWorker {
private int sequence;
public Worker(int sequence) {
this.sequence = sequence;
}
@Override
protected Object doInBackground() throws Exception {
System.out.println(sequence + "...");
Thread.sleep(500);
return null;
}
}
As a test, you could use something like...
ExecutorService es = Executors.newFixedThreadPool(1);
for (int index = 0; index < 10; index++) {
es.submit(new Worker(index));
}
es.shutdown();
(You don't need to call shutdown
, but otherwise my tested never allowed the JVM to terminate ;))
Which will run the workers in the order they are submitted.
Now, if you want to feed the values from one SwingWorker
to another, you could do something like...
public abstract class ChainedWorker<T, V> extends SwingWorker<T, V> {
private ChainedWorker<T, ?> next;
private T previousValue;
public ChainedWorker(ChainedWorker<T, ?> next) {
this.next = next;
}
public void setPreviousValue(T previousValue) {
this.previousValue = previousValue;
}
@Override
protected void done() {
try {
T previous = get();
if (next != null) {
next.setPreviousValue(previous);
next.execute();
}
} catch (InterruptedException | ExecutionException ex) {
ex.printStackTrace();
}
}
}
Which is simply a SwingWorker
which allows you to provide a link in the chain (the next worker to call), which passes the value that this SwingWorker
generated...or some such similar
Now, if you're really nuts and want to role your own, maybe something like...
public class ChainedWorkerBuilder {
private List<SwingWorker> workers;
private SwingWorker current;
public ChainedWorkerBuilder() {
workers = new ArrayList<>(25);
}
public ChainedWorkerBuilder add(SwingWorker worker) {
workers.add(worker);
return this;
}
public void execute() {
if (!workers.isEmpty()) {
SwingWorker worker = workers.remove(0);
worker.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
if ("state".equals(evt.getPropertyName())) {
SwingWorker source = (SwingWorker)evt.getSource();
switch (source.getState()) {
case DONE:
source.removePropertyChangeListener(this);
execute();
break;
}
}
}
});
}
}
}
2) How to update a textfield in my Welcome class, with the values from the Samp class.
I don't think I'm following your code directly, but, if you did something like...
SwingWorker<Boolean, Void>worker = new SwingWorker<Boolean, String>() {
protected Boolean doInBackground() throws Exception {
publish(fileName);
ZipUtility zu = new ZipUtility(fileName));
return zu.extract(fileName);
}
Then in the SwingWorker
s process
method you would be able to update the UI safely...
@Override
protected void process(List<String> chunks) {
// Grab the last element...
textfield.setText(chunks.get(chunks.size() - 1));
}
}