Java Swingworker one after another and update GUI - java

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 SwingWorkers 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));
}
}

Simply call execute() on worker2 from worker1's done:
final SwingWorker<Boolean, Void> worker2 = new SwingWorker<Boolean, Void>() {
...
}
final SwingWorker<Boolean, Void> worker1 = new SwingWorker<Boolean, Void>() {
#Override
protected Boolean doInBackground() throws Exception {
// Don't start a thread, do your work, otherwise the done will fire
// too early, also it's pointless to use worker and thread like that
return true;
}
// Can safely update the GUI from this method.
#Override
protected void done() {
// update some ui
// and start the second part
worker2.execute();
}
};

Related

Why stopping a SwingWorker does stop it immediately?

I'm using a SwingWorker to execute some repeatable tasks in background.
This is my Class:
public class CMyThread {
private SwingWorker<Object, Void> taskWorker;
public volatile boolean threadDone = false;
public CMyThread() {
}
#Override
public void stop() {
taskWorker.cancel(true);
}
#Override
public void start() {
taskWorker = new SwingWorker<Object, Void>() {
#Override
public Object doInBackground() {
while (!isCancelled()) {
// SOMETHING TIMECONSUMING THAT NEEDS TO BE DONE REPEATEDLY
CUtils.sleep(10000);
}
threadDone = true;
return null;
}
#Override
public void done() {
}
};
taskWorker.execute();
}
public void waitThreadToGentlyFinish() { // called when we call destroy() on the servlet
while (!threadDone) {
System.out.print("#");
CUtils.sleep(200);
}
}
}
And this is called this way:
CMyThread myThread = new CMyThread();
myThread.start();
Now, at one point I want to gently stop the thread.
So I call
myThread.stop();
myThread.waitThreadToGentlyFinish();
I'm expecting that the currently running [ACTION] is going to take time to finish, then only it will exit the loop and set the flag 'threadDone' to true. but what I actually see is that it exits the loop immediately and I never see any '#' characters displayed.
There is obviously something wrong in my code but I can't see the obvious.
Any idea guys ?

Swing worker override process <T,V>

I'm trying to override the process() method to ensure that some code runs in the EDT. I have made sure that <T,V> are matching throughout but it still won't let me override. Here is my code:
final SwingWorker<ArrayList<Block>,Integer[]> swingSlaveLabourer = new SwingWorker<ArrayList<Block>, Integer[]>() {
#Override
protected ArrayList<Block> doInBackground() throws Exception {
blockList.doHeavyWork()..
Integer [] status = new Integer[2];
status[0] = 1;
status[1] = 0;
this.process(status);
return blockList;
}
#Override //wont allow override
protected void process (Integer[] chunks){
progressBar.setValue(chunks[0]);
}
};
The process method takes a List<V> as argument. It represents all the data chunks that were published. You need to change your code to:
#Override
protected void process(List<Integer[]> chunks) {
// do something
}
You should not call directly process from the doInBackground method. Instead, you should call publish to publish each chunk of data.
Refer to the following example taken from the SwingWorker Javadoc:
class PrimeNumbersTask extends SwingWorker<List<Integer>, Integer> {
PrimeNumbersTask(JTextArea textArea, int numbersToFind) {
//initialize
}
#Override
public List<Integer> doInBackground() {
while (! enough && ! isCancelled()) {
number = nextPrimeNumber();
publish(number); // each computed number is published
setProgress(100 * numbers.size() / numbersToFind); // and progress updated
}
}
return numbers;
}
#Override
protected void process(List<Integer> chunks) {
// in the mean while, we print each published value to a textarea
for (int number : chunks) {
textArea.append(number + "\n");
}
}
}

How can i know threads jobs are done?

In class B how can i know jobs of threads are finished? In after properties some worker are running. In class B, I need to know if worker are done?
public class A implements InitializingBean{
public void method1(){
...
}
#Override
public void afterPropertiesSet() throws Exception {
System.out.print("test after properties set");
// send threads to executorService
ExecutorService executorService = Executors
.newFixedThreadPool(4);
for (int i = 0; i < 4; i++) {
Worker worker = new Worker();
executorService.submit(worker);
}
}
}
public class Worker implements Callable<Void>{
#Override
public void call(){
...
}
}
public class B{
public void methodB(){
A a = new A();
a.method1();
///Here How can i know the job of the workers are finished?
}
}
Use a listener/callback pattern to have the thread report completion to a listener. This simple example should show the process:
public interface ThreadCompleteListener {
void workComplete();
}
public class NotifyingThread extends Thread {
private Set<ThreadCompleteListener> listeners;
// setter method(s) for adding/removing listeners to go here
#Override
public void run() {
// do stuff
notifyListeners();
}
private void notifyListeners() {
for (ThreadCompleteListener listener : listeners) {
listener.workComplete(); // notify the listening class
}
}
}
in your listening class:
NotifyingThread t = new NotifyingThread();
t.addListener(new ThreadCompleteListener() {
void workComplete() {
// do something
}
});
t.start();
You could use a Future implementation for your thread. It provides a Future#isDone()
http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Future.html#isDone()
In general, it is usually more useful to be notified via a callback when jobs complete. However, since others have posted answers which follow that model, I'll instead post a solution that simply allows you to poll and ask whether the jobs are finished, in case this is what fits the needs of your application better.
public static interface InitializingBean{
public void afterPropertiesSet() throws Exception;
}
public static class A implements InitializingBean{
private List<Future<Void>> submittedJobs = Collections.synchronizedList(new ArrayList<Future<Void>>());
public void method1(){
//do stuff
}
#Override
public void afterPropertiesSet() throws Exception {
System.out.print("test after properties set");
// send threads to executorService
ExecutorService executorService = Executors
.newFixedThreadPool(4);
synchronized (submittedJobs) {
for (int i = 0; i < 4; i++) {
Worker worker = new Worker();
submittedJobs.add(executorService.submit(worker));
}
}
}
/**
* Allows you to poll whether all jobs are finished or not.
* #return
*/
public boolean areAllJobsFinished(){
synchronized (submittedJobs) {
for(Future<Void> task : submittedJobs){
if(!task.isDone()){
return false;
}
}
return true;
}
}
}
public static class Worker implements Callable<Void>{
#Override
public Void call(){
//do worker job
return null; //to satisfy compiler that we're returning something.
}
}
public static class B{
public void methodB(){
A a = new A();
a.method1();
if(a.areAllJobsFinished()){
System.out.println("Congrats, everything is done!");
} else {
System.out.println("There's still some work being done :-(");
}
}
}
If you'd like to wait in that thread that starts the ExecutorService, you can actually use the awaitTermination method.
At the end of you afterPropertiesSet method, you should add:
executorService.shutdown();
After this you then add:
executorService.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS)
This causes the thread to wait for all the executorService's tasks to be done and then continues. So place any code you want to execute after the call to awaitTermination.

Correct wait to fetch queue of threads

Ok, so, I have a java class in which every method must run in a thread.
only one thread is executed per time and at a specific time.
I've implemented like this, with a inner class that extends Thread.
private class MyOperation extends Thread {
public static final String M1 = "method1";
public static final String M2 = "method2";
public static final String M3 = "method3";
protected long scheduledStartTime = 0;
private String type;
public MyOperation(String type, long milliSecondsToWait) {
this.type = type;
scheduledStartTime = System.currentTimeMillis() + mlliSecondsToWait;
}
#Override
public void run() {
switch(type){
case M1:
doMethod1();
break;
case M2:
doMethod3();
break;
case M3:
doMethod3();
break;
}
setCurrentOperation(null);
}
}
private void setCurrentOperation(MyOperation task) {
synchronized (currentOperation) {
this.currentOperation = task;
}
}
then I have the Thread queue and the current running thread
private MyOperation currentOperation;
private Queue <MyOperation> operationList;
And I'm fetching tasks like this:
private void fetchTasks() {
new Thread() {
#Override
public void run() {
while(true) {
if(currentOperation == null && !operationList.isEmpty()) {
currentOperation = getOperation();
while(currentOperation.scheduledStartTime > System.currentTimeMillis()) {
// do nothing, wait for proper time;
}
currentOperation.start();
}
}
}
}.start();
}
private MyOperation getOperation() {
synchronized (operationList) {
return operationList.remove();
}
}
and I'm adding thread to the queue like this, for example:
addOperation(new MyOperation(M1, 5));
private void addOperation(MyOperation task) {
synchronized (operationList) {
operationList.add(task);
}
}
My questions are:
Is there a better way to run each method in a diffent thread?
Is this way of fetching the threads queue correct?
Thank you very much
Just a little thing: if your operationsList is empty or the currentOperation is not null your thread starts going in circles really fast.
You could use Thread.wait() and .notify() to avoid this.
Also you are using currentOperation with and without synchronized. This could get you into trouble.
Have you condsidered using a ScheduledExecutorService (java.util.concurrent) to schedule your tasks?

Using two threads and controlling one from the other in java?

Can someone please help me out.
I need to use two threads in a way that one thread will run permanently while(true) and will keep track of a positioning pointer (some random value coming in form a method). This thread has a logic, if the value equals something, it should start the new thread. And if the value does not equal it should stop the other thread.
Can someone give me some code snippet (block level) about how to realize this?
Create a class that implements Runnable. There you'll make a run() method.
Like:
public class StackOverflow implements Runnable{
private Thread t = null;
public void run(){
}
public void setAnotherThread(Thread t){
this.t = t;
}
}
On the main class, you'll create 2 instances of Thread based on the other class you created.
StackOverflow so1 = new StackOverflow();
StackOverflow so2 = new StackOverflow();
Thread t1 = new Thread(so1);
Thread t2 = new Thread(so2)
Then you set one thread in the other, so you can control it.
t1.setAnotherThread(so2);
t2.setAnotherThread(so1);
Then you do what you need to do.
Ok if I'm not mistaken, you want to have one class that could be run as a "Thread" or as a (lets call it) a "sub-Thread".
But how to do that with one run method? just declare a boolean variable that specifies whether the thread object is a sub-thread or a parent thread, and accordingly declare two constructors, one would create a parent thread and the other would create a sub thread, and to be able to stop the sub-thread declare another variable called stop that is default to false.
class ThreadExample extends Thread {
private boolean sub = false;
private ThreadExample subThread = null;
public boolean stop = false;
public ThreadExample() {
}
public ThreadExample(boolean sub) {
this.sub = sub;
}
public void run() {
if (sub) {
runSubMethod();
} else {
runParentMethod();
}
}
public void runParentMethod() {
boolean running = true;
while (running) {
if (getRandomValue() == some_other_value) {
if (getSubThread().isAlive()) {
continue;
}
getSubThread().start();
} else {
getSubThread().makeStop();
}
}
}
public void runSubMethod(){
while(true){
//do stuff
if (stop)
break;
}
}
public int getRandomValue() {
//your "Random Value"
return 0;
}
private ThreadExample getSubThread() {
if (subThread == null) {
subThread = new ThreadExample(true);
}
return subThread;
}
public void makeStop(){
stop = true;
}
}
Here is a simple idea how you can implement as many threads as you like in a class:
class MultipleThreads{
Runnable r1 = new Runnable() {
public void run() {
... code to be executed ...
}
};
//-----
Runnable r2 = new Runnable() {
public void run() {
... code to be executed ...
}
};
//--- continue as much you like
public static void main (String[] args){
Thread thr1 = new Thread(r1);
Thread thr2 = new Thread(r2);
thr1.start();
thr2.start();
}
}
Hope it helps!!
For communicating between the two threads, one simple solution is to set a boolean type volatile static variable, and have it set from one thread and put it in while(flag) condition in the other thread.
You can control the other thread using this method.
And if you have waiting processes or Thread.sleep() and you want to break the thread without having it to finish it, your interrupts by catching the exception.

Categories

Resources