SwingWorker executes done() before finishing doInBackground() - java

I have been reading about this, and from these posts, I get that I might be a bug
SwingWorker, done() is executed before process() calls are finished
The proper way to handle exceptions thrown by the SwingWorker.doInBackground
However in my case, there is nothing that calls the done method. This is how my worker works.
public static class collectingWorker extends SwingWorker<Void, Void> {
collectingWorker(String name) {
//initialize
threadName = name;
}
#Override
public Void doInBackground() {
loop = true;
while(loop){
//Code goes here
}
return null;
}
#Override
protected void done() {
System.out.println("loop: " + loop);
System.out.println("Collecting worker DONE");
try {
get();
} catch (CancellationException x) {
System.out.println("Cancelation");
// ...
} catch (InterruptedException x) {
System.out.println("Interruption");
// ...
} catch (ExecutionException x) {
System.out.println("Execution");
System.out.println(x.getMessage());
System.out.println(x.getCause());
// ...
}
}
}
And on a separate thread, I have a counter that waits x minutes before setting loop to false. What I see is that collectingWorker done method is executed before the x minutes that it should have waited, and to make things worse, it is completely random, sometimes it works, sometimes it fails after 3 minutes, sometimes it fails after 90 minutes.
And this is what I get from the prints in the done method, as you can see, the boolean "loop" is never set to false
loop: true
Collecting worker DONE
Execution
java.util.NoSuchElementException
java.util.NoSuchElementException
Any ideas or workarounds?

The logic nested within your while(loop) is throwing a NoSuchElementException causing your entire doInBackground() method to exit prematurely.

Related

How to make Thread in android run infinitely

Runnable updateSeekbar=new Runnable() {
#Override
public void run() {
try{
while (true) {
if (!isPlayerDead) {
Log.d("Threads", "Thread is running successfully.");
int progress=mediaPlayer.getCurrentPosition();
seekBar.setProgress(progress);
Log.d("Seekbar",seekBar.getProgress()+"");
Log.d("MediaProgress",mediaPlayer.getCurrentPosition()+"");
String s=modifyTime(mediaPlayer.getCurrentPosition() / 1000 / 60) + ":" + modifyTime((mediaPlayer.getCurrentPosition() / 1000) % 60);
progressTime.setText(s);
}
}
}
catch (Exception e){
e.printStackTrace();
}
}
};
Executor executor=new Executor() {
#Override
public void execute(Runnable command) {
Thread thread=new Thread(command);
thread.start();
}
};
executor.execute(updateSeekbar);
Actually the problem is that the thread dies before the mediaplayer can send updated position. I have made the thread in an endless while loop but still it dies. How can I make it run infinitely till the activity gets destroyed.
The thread only runs for a couple of seconds and then dies. I want it to run infinitely till the activity gets destroyed. All suggestions are welcome.
when mediaPlayer isn't in proper state and you try to call some improper method then some Exception may be thrown, and you are catching it OUTside while(true) loop. try to move try{}catch inside while(true), then your Thread will run infinitely
#Override
public void run() {
while (true) {
try{
if (!isPlayerDead) {
// current code
}
}
catch (Exception e){
e.printStackTrace();
}
SystemClock.sleep(20); // some bonus line
} // end of while
}
btw. give some rest for UI between iterations, e.g. by putting SystemClock.sleep(20); after every calculation (last line before closing bracket). you don't need so often progress refreshing, in current code it may happen even few times more often than system is capable to draw (in most often 60Hz case)

The proper way to handle exceptions thrown by the SwingWorker.doInBackground

The proper way to handle exceptions thrown by the doInBackground method of SwingWorker class is to invoke the get method from within the done method, as explained here and here.
The documentation for the get method states the following:
Waits if necessary for the computation to complete, and then retrieves
its result.
Note: calling get on the Event Dispatch Thread blocks all
events, including repaints, from being processed until this
SwingWorker is complete.
Therefore, if the get method causes a waiting within the done method, in fact it would block the Event Dispatch Thread, since the done method is executed on EDT.
However, after performing a simple test of the proposed solution, you may notice that the EDT is not blocked: this behavior occurs because the get method is invoked within the done method, so get is invoked after the result of the operation was calculated, and therefore the call to it will not block the EDT. Is this motivation correct?
Therefore, if the get method causes a waiting within the done method, in fact it would block the Event Dispatch Thread, since the done method is executed on EDT.
Actually, if done is called, the doInBackground has already returned, therefore calling get within done will NOT block the Event Dispatching Thread.
The same goes if you are using the PropertyChangeListener support and monitoring the change in state to DONE
Updated
So, after having a look at SwingWorker calls 'done' before the 'doInBackground' is finished, which would mean that calling get on a cancelled worker would block the EDT indeventially, the basic work around is actually to ignore the return result by checking the SwingWorker#isCancelled state. Let's face it, if the worker is cancelled, the return result is unknown/undefined, so it's best NOT to try and get it.
As an example (based on the code from the bug)
import java.util.concurrent.ExecutionException;
import javax.swing.SwingWorker;
public class Main {
public static void main(String[] args) throws InterruptedException {
SwingWorker<String, String> worker = new SwingWorker<String, String>() {
#Override
protected String doInBackground() throws Exception {
try {
while (!Thread.currentThread().isInterrupted()) {
System.out.println("Working...");
Thread.sleep(1000);
}
} catch (InterruptedException ex) {
System.out.println("Got interrupted!");
}
try {
System.out.println("Cleaning up");
Thread.sleep(10000);
System.out.println("Done cleaning");
} catch (InterruptedException ex) {
System.out.println("Got interrupted second time!");
}
return null;
}
#Override
protected void done() {
System.out.println("Done");
if (!isCancelled()) {
long start = System.currentTimeMillis();
try {
get();
} catch (InterruptedException | ExecutionException ex) {
ex.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println("Took " + ((end - start) / 1000d));
} else {
System.out.println("Was cancelled");
}
}
};
worker.execute();
Thread.sleep(10000);
worker.cancel(true);
Thread.sleep(20000);
}
}
#Override
protected void done()
{
try
{
if(!super.isCancelled())
{
super.get();
}
}
catch(Exception ex)
{
ex.printStackTrace();
}
}

Future cancel(boolean b) method not working when used in GUI application

I have the following code:
public class Cancelling {
public static void main(String args[]) {
ToBeCancelled tbc = new ToBeCancelled();
ForkJoinPool pool = new ForkJoinPool(1);
Future<?> future = pool.submit(tbc);
try {
Thread.sleep(3000);
} catch (InterruptedException ie) {}
future.cancel(true);
if (future.isCancelled())
System.out.println("The task has been cancelled");
}
}
With the ToBeCancelled class being:
public class ToBeCancelled implements Runnable {
public void run() {
try {
Thread.sleep(5000); // should throw exception here
} catch (Exception e) {
return; // should exit
}
System.out.println("I should never be able to print this");
}
}
The main thread should start, wait for 3 seconds, and then cancel the ToBeCancelled task by using future.cancel(true). It then should print The task has been cancelled, while the task never gets to print its message.
At least, this is what happens when I start it from console.
As I start it from a GUI application with a TextArea where the output is redirected to, that's not the case. The main method does print The task has been cancelled, but the task also prints I should never be able to print this.
This is driving me insane. From what I understand the task should receive its cancel command while on the Thread.sleep(5000) method, which would fire an exception that is consequently caught and makes the thread return. But it doesn't happen and yet the main thinks it has been cancelled. It's like the cancel method is completely ignored by the task.
I've tried everything I could think of, checking on the returned value of cancel, making the task wait longer, using Thread.currentThread().isInterrupted(), but nothing works.
I feel like I'm missing something really simple, but I just can't find what it is. Any idea?
In case anyone thinks it might be something on the GUI application, this is the method that starts the program:
public static void StartProgram(String name) {
try {
Method m = Class.forName(name).getDeclaredMethod("main",String[].class);
Object[] args = new Object[1];
String s[] = new String[2];
s[0] = tf1.getText();
s[1] = tf2.getText();
args[0] = s;
t = new Thread(new ProgramStarter(args, m));
t.start();
} catch (Exception e) {
e.printStackTrace();
}
}
With ProgramStarter being:
public class ProgramStarter implements Runnable {
private Object[] args;
private Method m;
public ProgramStarter(Object args[], Method m) {
this.args = args;
this.m = m;
}
public void run() {
try {
m.invoke(null, args);
} catch (Exception e) {
e.printStackTrace();
}
}
}
The problem is that your verification is wrong. You think that your code works when running from the console but in fact, it fails in all cases. When running from the console your main thread ends after the attempt to cancel the future and the JVM will terminate as there are only daemon threads left in the JVM. Due to the JVM termination you don’t notice that the cancellation did not work.
When adding a sleep at the end of your main method to delay the JVM termination you will notice that "I should never be able to print this" is printed when running from the console as well. So the only difference between GUI and console version is that the running Event Dispatch Thread prevents the JVM from terminating so you see that it doesn’t work.
The bottom line is: don’t use ForkJoinPool unless you have a reason for this.
Since you just want submit to a simple single-background-thread executor, you can create the executor using Executors.newFixedThreadPool(1). This has less unexpected behavior: it’s thread is non-daemon by default and it’s Future will cancel with interruption as expected.

Stopping a thread in a Tomcat Application - which method?

I'm using the below implementation to stop a thread in Tomcat. The code works, but I'm wondering two things:
Is it necessary to have Thread.sleep() in the try statement of MyConsumer.java?
Instead of checking for my boolean flag, running, should I remove the concept of a flag and just check for while(!Thread.currentThread().isInterrupted)?
ServletContextListener:
public final class ApplicationListener implements ServletContextListener {
private Thread thread = null;
private MyConsumer k = null;
public ApplicationListener() {
}
#Override
public void contextInitialized(ServletContextEvent event) {
k = new MyConsumer();
thread = new Thread(k);
thread.start();
}
#Override
public void contextDestroyed(ServletContextEvent event) {
if (thread != null) {
k.terminate();
try {
thread.join();
} catch (InterruptedException ex) {
Logger.getLogger(ApplicationListener.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
}
MyConsumer.java:
public class MyConsumer implements Runnable {
private volatile boolean running = true;
public MyConsumer() {
}
public void terminate() {
running = false;
}
#Override
public void run() {
while (running) {
try {
doStuff();
Thread.sleep((long) 1000);
} catch (InterruptedException ex) {
Logger.getLogger(MyConsumer.class.getName()).log(Level.SEVERE, null, ex);
running = false;
}
}
}
Is it necessary to have Thread.sleep() in the try statement of MyConsumer.java
No. The sleep call, I presume, is there to make sure that doStuff() is executed with an interval of 1 second between every invocation, rather than executed continuously. If you want this 1 second interval, you need to leave the sleep call there. If you want doStuff() to be executed continuously, then you need to remove the sleep.
Instead of checking for my boolean flag, running, should I remove the concept of a flag and just check for while(!Thread.currentThread().isInterrupted)?
Yes, that's what I would indeed do. It would remove the need for the flag, and would allow stopping the thread as soon as possible, rather than having to wait for the sleep call to return, after 1 second. The other advantage is that you can check if the thread is interrupted inside the doStuff() method, in case it's a long-running method that you want to stop ASAP.
There's no reason for your thread to sleep just to check for interruptions. You can call Thread.interupted() there instead.
Regarding the boolean running flag, it provides similar functionality of interrupted, except that it's not triggered by methods that throw InterruptedException. Depending on whether it makes sense to stop normal flow of operation in those methods, you should use one or the other mechanism, but not both.
See http://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html for a good overview of how interrupts are used.

Stopping looping thread in Java

I'm using a thread that is continuously reading from a queue.
Something like:
public void run() {
Object obj;
while(true) {
synchronized(objectsQueue) {
if(objectesQueue.isEmpty()) {
try {
objectesQueue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
obj = objectesQueue.poll();
}
}
// Do something with the Object obj
}
}
What is the best way to stop this thread?
I see two options:
1 - Since Thread.stop() is deprecated, I can implement a stopThisThread() method that uses a n atomic check-condition variable.
2 - Send a Death Event object or something like that to the queue. When the thread fetches a death event, it exits.
I prefer the 1st way, however, I don't know when to call the stopThisThread() method, as something might be on it's way to the queue and the stop signal can arrive first (not desirable).
Any suggestions?
The DeathEvent (or as it is often call, "poison pill") approach works well if you need to complete all of the work on the queue before shutting down. The problem is that this could take a long time.
If you want to stop as soon as possible, I suggest you do this
BlockingQueue<O> queue = ...
...
public void run() {
try {
// The following test is necessary to get fast interrupts. If
// it is replaced with 'true', the queue will be drained before
// the interrupt is noticed. (Thanks Tim)
while (!Thread.interrupted()) {
O obj = queue.take();
doSomething(obj);
}
} catch (InterruptedException ex) {
// We are done.
}
}
To stop the thread t that instantiated with that run method, simply call t.interrupt();.
If you compare the code above with other answers, you will notice how using a BlockingQueue and Thread.interrupt() simplifies the solution.
I would also claim that an extra stop flag is unnecessary, and in the big picture, potentially harmful. A well-behaved worker thread should respect an interrupt. An unexpected interrupt simply means that the worker is being run in a context that the original programmer did not anticipate. The best thing is if the worker to does what it is told to do ... i.e. it should stop ... whether or not this fits with the original programmer's conception.
Why not use a scheduler which you simply can stop when required? The standard scheduler supports repeated scheduling which also waits for the worker thread to finish before rescheduling a new run.
ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
service.scheduleWithFixedDelay(myThread, 1, 10, TimeUnit.SECONDS);
this sample would run your thread with a delay of 10 sec, that means when one run finishes, it restarts it 10 seconds later. And instead of having to reinvent the wheel you get
service.shutdown()
the while(true) is not necessary anymore.
ScheduledExecutorService Javadoc
In your reader thread have a boolean variable stop. When you wish for this thread to stop set thius to true and interrupt the thread. Within the reader thread when safe (when you don't have an unprocessed object) check the status of the stop variable and return out of the loop if set. as per below.
public class readerThread extends Thread{
private volitile boolean stop = false;
public void stopSoon(){
stop = true;
this.interrupt();
}
public void run() {
Object obj;
while(true) {
if(stop){
return;
}
synchronized(objectsQueue) {
if(objectesQueue.isEmpty()) {
try {
objectesQueue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
if(stop){
return;
}
obj = objectesQueue.poll();
// Do something with the Object obj
}
}
}
}
public class OtherClass{
ThreadReader reader;
private void start(){
reader = ...;
reader.start();
}
private void stop(){
reader.stopSoon();
reader.join(); // Wait for thread to stop if nessasery.
}
}
Approach 1 is the preferred one.
Simply set a volatile stop field to true and call interrupt() on the running thread. This will force any I/O methods that wait to return with an InterruptedException (and if your library is written correctly this will be handled gracefully).
I think your two cases actually exhibit the same potential behavior. For the second case consider Thread A adds the DeathEvent after which Thread B adds a FooEvent. When your job Thread receives the DeathEvent there is still a FooEvent behind it, which is the same scenario you are describing in Option 1, unless you try to clear the queue before returning, but then you are essentially keeping the thread alive, when what you are trying to do is stop it.
I agree with you that the first option is more desirable. A potential solution would depend on how your queue is populated. If it is a part of your work thread class you could have your stopThisThread() method set a flag that would return an appropriate value (or throw Exception) from the enqueuing call i.e.:
MyThread extends Thread{
boolean running = true;
public void run(){
while(running){
try{
//process queue...
}catch(InterruptedExcpetion e){
...
}
}
}
public void stopThisThread(){
running = false;
interrupt();
}
public boolean enqueue(Object o){
if(!running){
return false;
OR
throw new ThreadNotRunningException();
}
queue.add(o);
return true;
}
}
It would then be the responsibility of the object attempting to enqueue the Event to deal with it appropriately, but at the least it will know that the event is not in the queue, and will not be processed.
I usually put a flag in the class that has the Thread in it and in my Thread code I would do. (NOTE: Instead of while(true) I do while(flag))
Then create a method in the class to set the flag to false;
private volatile bool flag = true;
public void stopThread()
{
flag = false;
}
public void run() {
Object obj;
while(flag) {
synchronized(objectsQueue) {
if(objectesQueue.isEmpty()) {
try {
objectesQueue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
obj = objectesQueue.poll();
}
}
// Do something with the Object obj
}
}

Categories

Resources