Java: wait for boolean to change - java

I was looking at the current thread:
How to create a thread that waits for a boolean variable to become true?
Everyone seemed to disagree with each other and noone exaplined themselves enough so I shall present this in the easiest way. Here is my code as of today.
boolean connecting = false;
public static void main(String[] args) {
initUI();
while(true) {
if(connecting) {
connecting = false;
doSomething();
}
};
}
initUI() is a mthod which initiates the User Interface. When the user clicks a button in that class called "Connect" it will call it's action listener and set the boolean "connecting" to "true". When it enters the if area it will then reset the boolean to "false" and run the code which I want.
This works, however... It uses far too much CPU.
If I directly set the buttons action listener to the doSomething() method the program jams (and should) as the action listener method needs to finish in order for the button to reset. However the doSomething() has loops (it's a chat program) so it will not return to the original while (which is displayed here in code) until he disconnects.
So my question, is there anyway to "wait" for the boolean to change to true. For example a listener?
ANSWER: Thanks to Joni I implemented a Thread.
The buttons actionListener now includes:
(new connectThread()).start();
And my thread looks like this:
public class connectThread extends Thread {
public void run() {
ui.btn.setEnabled(false);
doSomething();
ui.btn.setEnabled(true);
}
}
As for the question title, waiting for a boolean to change, as another person explained an event listener could be set.

So my question, is there anyway to "wait" for the boolean to change to true.
You can't do it (efficiently and responsively) with a bare boolean variable. A sleep / test loop is a poor solution because it will either be expensive or non-responsive. If the sleep interval is small you waste CPU, and if you make it larger your application takes a (relatively) long time to notice the state change.
But if the boolean is updated via a method (e.g. a setter) then you can code the setter to:
notify other threads that are waiting in a mutex; e.g. https://stackoverflow.com/a/12884570/139985, or
call some "event listener" callback.

Go back to the code where the event listener calls doSomething(), but with one change: start a new thread that runs doSomething() rather than call it directly. You can find a complete example of how to do this in the Java Tutorial: Simple Background Tasks. The SwingWorker API documentation also has an example.

You are on the wrong track - "busy waiting" as you are doing here is almost always the wrong idea, since it just needlessly burns CPU time.
From what I understand you want to react to a button-press without locking up the UI thread. There is no need to have the thread already waiting before that point - just start it up once the button is pushed, as Joni suggests. If you want to ensure that only one button press is processed at a time, you could use a thread pool with a single thread (see SingleThreadExecutor).
I also want to point out an important mistake in your example code: connecting needs to be made volatile to tell the compiler that the value could change from another thread. As it is, there is no guarantee that your worker thread will ever see the value change, so it could just loop infinitely even if you set connecting to true in another thread.

You can either put in a Thread.sleep(100); in the loop, so it's not a tight loop like that, which can easily freeze the rest of the threads.
What you can also do is use a wait/notify mechanism. Just have a shared Object, signaller... have the "while(true)" call "signaller.wait()", then, after your other thread sets the flag (it might not need to), it can call "signaller.notifyAll()" which will let the other thread run its next iteration, and see that the flag is set.

In your listener, instead of setting a flag, you could run doSomething() in a new thread. In the example below, ThreadTest is actually the class where you currently have your listener method (I've called it onClick()).
public class ThreadTest {
private ExecutorService service;
public ThreadTest() {
service = Executors.newFixedThreadPool(10);
}
// Button click listener.
public void onClick() {
service.submit(new Runnable() {
#Override
public void run() {
doSomething();
}
});
}
public void doSomething() {}
}

Related

order of execution mixed up with use of Thread.sleep

I am writing a method for my android app where I make a RecyclerView invisible, and a ProgressBar visible. I then perform some logic, before resetting the two views to their original visibility state.
With just the setVisibility() call, it works as intended. However, I am also required to call Thread.sleep() to force a wait directly after performing the logic.
Initially, I have had trouble trying to call setVisibility() to begin with. It simply did nothing. I have found many questions with similar problems, but not similar enough; I was unable to find a solution specific to my problem.
Creating a new method to simply call setVisibility(), I found that this worked as intended. I started to move my logic over, line by line, until it stopped working.
As it stands, it still technically sets the visibility correctly. However, despite being several lines down from the setVisibility() calls, my Thread.sleep() seems to be forcing itself to run before setVisibility(). I believe this was my original problem; Logically, the commands after Thread.sleep() would run directly after, and effectivley undo my setVisibility() on the very next frame.
This is my method:
public void SetMainInvisible(){
mRecyclerView.setVisibility(View.INVISIBLE);
mMainProgressBar.setVisibility(View.VISIBLE);
mTrainAdapter.RefreshAll();
Log.d("TEST", "FINISHED VIS");
try {
Thread.sleep(sSleepTime);
} catch (InterruptedException exception) {
// In the nature of a simple "Thread.sleep", there is no real reason to respond
// directly to interruption. If the sleep request is interrupted, the best course
// of action to preserve user experience is to simply move on. That said, we will
// still "re-enable" the flag that tells us the thread was interrupted, in case we
// should need to clarify if there was an interruption, later on. As is, this flag
// will be reset to false as soon as the exception is thrown.
Thread.currentThread().interrupt();
}
}
From my direct observation, when it calls, my log prints "FINISHED VIS". My application then enters the Thread.sleep() stage, and waits for 3 seconds. My views then change their visibility, as directed by the very first lines. I do not have setVisibility() anywhere else in my code.
I have tried reading further on Thread.sleep, but all references suggest exactly what I have been taught; when it executes, it forces the process to "sleep" for a set period of time. It should not force the method to postpone all other logic until it returns. On the contrary, the examples at Tutorial Point provide logic and output that suggests normal operation.
I know that I should never really be calling Thread.sleep(), but it is a direct requirement of the exercise I am completing for University. Why is Thread.sleep() forcing itself to run before any other command, despite being at the end of the method?
Changing visibility (or any other layout/drawing operation) does not have any immediate, synchronous effect on your user interface. Instead, essentially just a message is posted on the UI thread's message queue to take care of the change later.
Calling sleep() on the UI thread is a no-no. You're blocking the UI thread and execution does not return to the message handler that would take care of the relayout/redraw messages waiting in the queue. Only after the sleep() does the execution return to the message handler.
If you need to add delays to your code, use e.g. Handler#postDelayed() to post a Runnable of your own to the UI thread's message queue to be executed after a delay.
Working off #laalto's answer, I decided to test my method in the form of an AsyncTask, before looking into Handler#postDelayed() (This is something we have not covered, and I am completely unfamiliar with it). I am happy to report that it works exactly as intended.
This might be a suitable alternative, for those that are more familiar with implementing AsyncTask.
First, I implement an inner asynchronous class as follows:
private class RefreshTimesAsyncTask extends AsyncTask<Void, Void, Void> {
private long mSleepTime;
public RefreshTimesAsyncTask (long sleepTime) {
mSleepTime = sleepTime;
}
#Override
protected void onPreExecute() {
mMainProgressBar.setVisibility(View.VISIBLE);
mRecyclerView.setVisibility(View.GONE);
mTrainAdapter.RefreshAll();
}
#Override
protected Void doInBackground(Void... params) {
try {
Thread.sleep(mSleepTime);
} catch (InterruptedException exception) {
// ...
Thread.currentThread().interrupt();
}
return null;
}
#Override
protected void onPostExecute(Void result) {
mMainProgressBar.setVisibility(View.GONE);
mRecyclerView.setVisibility(View.VISIBLE);
}
}
I then simply call new RefreshTimesAsyncTask(sSleepTime).execute();, rather than my previous function call of SetMainInvisible(). I also set static long sSleepTime=3000 in the variable declaration of my main class, due to the nature of being required to set this value as a static, and not being able to declare static variables in an inner class.

Append text to JTextArea in a try catch block [duplicate]

I have a swing application which stores a list of objects. When the users clicks a button,
I want to perform two operations on each object in the list, and then once that is complete, graph the results in a JPanel. I've been trying SwingWorker, Callable & Runnable to do the processing, but no matter what I do, while processing the list (which can take up to a few minutes, as it is IO bound), the GUI is locked up.
I have a feeling it's probably the way I'm calling the threads or something, or could it be to do with the graphing function? That isn't threaded as it is very quick.
I have to do the two processing stages in order too, so what is the best way to ensure the second one has waited on the first? I've used join(), and then
while(x.isAlive())
{
Thread.sleep(1000);
}
to try and ensure this, but I'm worried this could be the cause of my problem too.
I've been looking everywhere for some pointers, but since I can't find any I'm sure I'm doing something stupid here.
The problem is, your long running task is blocking the Thread that keeps the GUI responsive.
What you will need to do is put the long running task on another thread.
Some common ways of doing this are using Timers or a SwingWorker.
The Java tutorials have lots of information regarding these things in their lesson in concurrency.
To make sure the first task finishes before the second, just put them both on the same thread. That way you won't have to worry about keeping two different threads timed correctly.
Here is a sample implementation of a SwingWorkerFor your case:
public class YourTaskSwingWorkerSwingWorker extends SwingWorker<List<Object>, Void> {
private List<Object> list
public YourClassSwingWorker(List<Object> theOriginalList){
list = theOriginalList;
}
#Override
public List<Object> doInBackground() {
// Do the first opperation on the list
// Do the second opperation on the list
return list;
}
#Override
public void done() {
// Update the GUI with the updated list.
}
}
To use this code, when the event to modify the list is fired, create a new SwingWorker and tell it to start.
You are not returning the swing thread properly. I realize you are using callable/runnable but i'm guessing you are not doing it right (although you didn't post enough code to know for sure).
The basic structure would be:
swingMethod() { // Okay, this is a button callback, we now own the swing thread
Thread t=new Thread(new ActuallyDoStuff());
t.start();
}
public class ActuallyDoStuff() implements Runnable {
public void run() {
// this is where you actually do the work
}
}
This is just off the top of my head, but I'm guessing that you either aren't doing the thread.start and are instead calling the run method directly, or you are doing something else in the first method that locks it up (like thread.join). Neither of these would free up the swing thread. The first method MUST return quickly, the run() method can take as long as it wants.
If you are doing a thread.join in the first method, then the thread is NOT being returned to the system!
Edit: (Second edit actually)
I think to speak to the problem you are actually feeling--you might want to think more in terms of a model/view/controller system. The code you are writing is the controller (the view is generally considered to be the components on the screen--view/controller are usually very tightly bound).
When your controller gets the event, it should pass the work off to your model. The view is then out of the picture. It does not wait for the model, it's just done.
When your model is finished, it needs to then tell the controller to do something else. It does this through one of the invoke methods. This transfers control back to the controller and you go on your merry way. If you think about it this way, separating control and deliberately passing it back and forth doesn't feel so bulky, and it's actually very common to do it this way.
It sounds like the problem might be that you are waiting on the threads to finish from inside the GUI thread. Your GUI thread should not wait on these threads, instead you should have the worker threads invoke some method on the GUI thread that sets a flag. When both flags are set then you know both threads finished and you can do the graph.
I can't really speak to the swing threading model, but:
I have to do the two processing stages in order too, so what is the best way to ensure the second one has waited on the first?
For this kind of functionality, I'd suggest you create two worker threads, and embed a JMS broker. Deliver work to the two threads by passing messages into JMS queues that they read from. Your GUI thread is free to examine the queues to determine when work is happening and represent the state of play in your UI.
The solution to my problem was a mixture of jjnguy and Bill K's answers, so thanks very much for that guys. I needed to use threads within a SwingWorker like this:
public class Worker extends SwingWorker<Void, Void>
{
private List<Object> list;
public YourClassSwingWorker(List<Object> theOriginalList){
list = theOriginalList;
}
#Override
public List<Object> doInBackground() {
Thread t = new Thread(new ProcessorThread(list));
t.start();
}
#Override
public void done() {
// draw graph on GUI
}
}
class ProcessorThread implements Runnable {
//do lots of IO stuff
Thread t2 = new Thread(new SecondProcess());
t2.start();
}
This made sure all the work was being done by worker threads away from the GUI, and also ensuring that the SwingWorker itself wasn't doing all of the work, which might have been a problem.

What is the safest/best way to stop a thread and run some clean-up code

As part of my efforts to implement a voice recognition program in Java I have implemented the actual voice recognition code in a separate thread. The main thread handles the GUI interface and receives constant updates from the voice recognition thread when words are identified.
When the user clicks the Quit button in the GUI on the main thread I want this thread to immediately run some clean-up code and terminate.
I currently have the following:
public class VoiceRecognitionCore extends SwingWorker<List<String>, String>
{
//Variables and things here
#Override
public List<String> doInBackground() throws VoiceRecognitionException
{
//Code here
while(continueVoiceRecog == true)
{
//More code
Result result = recog.recognize();
//More code
}
}
}
Where I rely on the while loop to constantly check the status of continueVoiceRecog which will be set to false by the main thread when the user clicks "Quit".
The current problem is that the code can sometimes permanently sit inside the recog.recognize() method so it'll never get back to the while check. It should be noted that this was always intended as a temporary solution.
I'm thinking of extending doInBackground() to catch InterruptedException and will use a thread interrupt which will call a cleanup method to deallocate any resources being used.
What is the safest/best approach for this scenario? If it is what I propose, are there any potential issues I should be aware of?
Using thread interrupt is perfectly acceptable route - however in your example (using SwingWorker) you can use the cancel() method instead.
In the calling code after having created the VoiceRecognitionCore you can cancel() the worker exit button action listener:
final VoiceRecognitionCore worker = new VoicRecognitionCore();
worker.execute();
JButton exitButton = new JButton("Exit");
exitButton.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
// True passed to Interrupt the underlying thread.
worker.cancel(true);
// other clean-up
// then System.exit(0); ?
}
});
However, this approach will need to check the status of: Thread.isInterrupted() within your recognize() method. (see link: http://docs.oracle.com/javase/tutorial/uiswing/concurrency/cancel.html)
If you are needing to clean-up stuff and don't have ability to check the isInterrupted() flag - perhaps best approach is to have a method to be able to determine if your recog object is mid recognizing... and when the exit button is pressed - if recog.isRecognizing() then do clean up and then exit?
PS. One might argue that if you are doing a System.exit(0); anyway, then cleanly exiting that loop is perhaps unnecessary ... but it depends if you are doing other clean-up in there... such as finishing writing to files etc.

Is it possible to wait for methods that aren't in Threads to finish in Java?

I have an object which does some computation, then for each iteraction I want to draw what happens. While the drawing is happening, I want it to wait.
This is what I did, basically:
synchronized public void compute()
{
other.mark(variable);
try
{
wait();
}
catch(InterruptedException e)
{
}
}
in the OtherClass, I have
synchronized public void mark(int var)
{
//change some stuff
repaint();
notify();
}
What happens is that compute() waits forever. I thought this was going to work, since no erros were given by the compiler. Neither class implements Runnable or extends Thread, so maybe that's the problem? I'm not sure since I figure I'd be warned if these objects couldn't use such methods.
I'm thinking it might be an error regarding the logic of the program itself, but in a nutshell that's what I have.
Your question suggests that you want to perform some operation that updates the GUI state either when it is finished or notifies the GUI of its progress. This is what SwingWorker was designed for. There are some examples on the linked javadoc for both cases.
This simply does not work as you think it does. From Javadoc of wait() method (emphasis mine):
Causes current thread to wait until another thread invokes the notify() method or the notifyAll() method for this object.
There is obviously no other thread in your program to wake up the sleeping compute() method.
To solve your particular problem, you either have to have two threads, or, alternatively, implement compute() method as resumable, something like this in pseudo Java:
ComputeStatus status = new ComputeStatus();
do {
compute(status); // compute iteration
mark(status); // draw iteration
status.next(); // next iteration
} while (!status.isFinished());
Here ComputeStatus hold the current state of computation, and comupte() knows how to continue the calculation from that state. Whether you change the status in compute() or in main loop, is up to you and the problem you're solving.
Since your program is a GUI program (I'm gathering by the repaint() call), it is inherently multi-threaded, even if you don't know it. (If not, it will behave very badly.)
If you are not using Threads, then you cannot use wait/notify or any other kind of synchronization, since there aren't two threads to synchronize. But you don't have to explicitly use Threads, necessarily, in a GUI program to end up using Threads.
Note that the Java compiler won't warn you if you use methods relying on Threads but don't actually use Threads in any way.
You have one of the following problems:
1) You are using Threads without knowing about it and you are using two different monitor objects. Thus, when you call notify(), it is notifying the monitor for that object, but not for the first object where you are calling wait(). There are many possible solutions. One of the easiest is to use the JDK 5 concurrency utilities to do this, which are MUCH nicer than the built-in base monitor wait/notify methods. Or,
2) You are running in a single Thread and the wait/notify does not good. It just doesn't make sense in a single-Threaded program to wait for another Thread to notify -- there's no other thread that can do so.
Assuming that you are actually using more than one Thread, a good way to solve this with Java 5 and later is with a semaphore, perhaps by, in the class containing mark() and simplifying a bit:
private final Semaphore sem = new Semaphore(1);
public void mark(int var) {
sem.acquire();
//change some stuff
repaint();
sem.release();
}
waitForSemaphore() {
sem.acquire();
}
and then in compute, call waitForSemaphore() when you want to wait to be notified by mark(). Because mark() already acquired the semaphore, you'll have to wait for mark() to release the semaphore before compute will be able to get it by calling waitForSemaphore().
The repaint method registers the need to paint the component but it doesn't actually paint it, however Java will repaint the object the next chance it gets. If you are trying to make something like an animation then there is no purpose to wait for repaint to complete. Instead I recommend you use a timer. Now you have 2 options for timers. If you are updating something where the timing doesn't have to be exact then often javax.swing.Timer is what you are looking for. You use it like this:
//imports (before class definition)
import javax.swing.Timer;
import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
//put this code where you want to start doing calculations
int delay = 1000; //milliseconds
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
//update your calculations
model.calculate();
//tell Java to call paint at the next chance it gets
viewer.repaint();
}
};
new Timer(delay, taskPerformer).start();
In the above code the model is the object you want to perform the calculations on and the viewer is the object that paints based on the model.
The swing timer is not very exact in its timing which is fine for lots of things but sometimes you need code to be scheduled more exactly. In that case you may want to use the java.util.Timer class. You use it like this:
//imports (before class definition)
import java.util.Timer;
import java.util.TimerTask;
//inner class that does the calculations
public class CalculateTask extends TimerTask {
public void run() {
model.calculate();
view.repaint();
}
}
//put this code where you want to start doing calculations
int delay = 0;//time before running CalculateTask.run()
int repeat = 1000; //time between each subsequent rums of CalculateTask.run()
boolean isDaemon = true;//allow java to shutdown without stopping timer
Timer timer = new Timer(isDaemon);
timer.scheduleAtFixedRate(new CalculateTask(), delay, repeat);
The wait() never gets released because you are not synchronizing on the same object. Your compute method is in a different object and therefore the notify call is not sharing the same monitor as your mark() method.
The wait/notify mechanism are for shared monitors, that is, they have to be sharing the same thread locking mechanism.
The only way the wait() will 'wake up' is if another thread calls notify() from within a synchronization block on the same object.
Unfortunately wait() will never stop waiting.
Main reason, look were you put your notify().
It is being called by the same thread, and can't wake itself up.
It's quite simple. mark(int var) will already have finished running by the time you get to the wait() command, so there is no way that the notify() in mark(int var) can wake it.
Object.wait() and Object.notify() are only for use by threads. In the code you show, the method mark(int var) will not return until it is finished, there is no need to wait. Also, synchronized methods are only needed in a multi-threaded program.
Your code should be:
public void compute()
{
other.mark(variable);
}
public void mark(int var)
{
//change some stuff
repaint();
}

How to abort a thread in a fast and clean way in java?

Here is my problem: I've got a dialog with some parameters that the user can change (via a spinner for example). Each time one of these parameters is changed, I launch a thread to update a 3D view according to the new parameter value.
If the user changes another value (or the same value again by clicking many times on the spinner arrow) while the first thread is working, I would like to abort the first thread (and the update of the 3D view) and launch a new one with the latest parameter value.
How can I do something like that?
PS: There is no loop in the run() method of my thread, so checking for a flag is not an option: the thread updating the 3D view basically only calls a single method that is very long to execute. I can't add any flag in this method asking to abort either as I do not have access to its code.
Try interrupt() as some have said to see if it makes any difference to your thread. If not, try destroying or closing a resource that will make the thread stop. That has a chance of being a little better than trying to throw Thread.stop() at it.
If performance is tolerable, you might view each 3D update as a discrete non-interruptible event and just let it run through to conclusion, checking afterward if there's a new latest update to perform. This might make the GUI a little choppy to users, as they would be able to make five changes, then see the graphical results from how things were five changes ago, then see the result of their latest change. But depending on how long this process is, it might be tolerable, and it would avoid having to kill the thread. Design might look like this:
boolean stopFlag = false;
Object[] latestArgs = null;
public void run() {
while (!stopFlag) {
if (latestArgs != null) {
Object[] args = latestArgs;
latestArgs = null;
perform3dUpdate(args);
} else {
Thread.sleep(500);
}
}
}
public void endThread() {
stopFlag = true;
}
public void updateSettings(Object[] args) {
latestArgs = args;
}
The thread that is updating the 3D view should periodically check some flag (use a volatile boolean) to see if it should terminate. When you want to abort the thread, just set the flag. When the thread next checks the flag, it should simply break out of whatever loop it is using to update the view and return from its run method.
If you truly cannot access the code the Thread is running to have it check a flag, then there is no safe way to stop the Thread. Does this Thread ever terminate normally before your application completes? If so, what causes it to stop?
If it runs for some long period of time, and you simply must end it, you can consider using the deprecated Thread.stop() method. However, it was deprecated for a good reason. If that Thread is stopped while in the middle of some operation that leaves something in an inconsistent state or some resource not cleaned up properly, then you could be in trouble. Here's a note from the documentation:
This method is inherently unsafe.
Stopping a thread with Thread.stop
causes it to unlock all of the
monitors that it has locked (as a
natural consequence of the unchecked
ThreadDeath exception propagating up
the stack). If any of the objects
previously protected by these monitors
were in an inconsistent state, the
damaged objects become visible to
other threads, potentially resulting
in arbitrary behavior. Many uses of
stop should be replaced by code that
simply modifies some variable to
indicate that the target thread should
stop running. The target thread should
check this variable regularly, and
return from its run method in an
orderly fashion if the variable
indicates that it is to stop running.
If the target thread waits for long
periods (on a condition variable, for
example), the interrupt method should
be used to interrupt the wait. For
more information, see Why are
Thread.stop, Thread.suspend and
Thread.resume Deprecated?
Instead of rolling your own boolean flag, why not just use the thread interrupt mechanism already in Java threads? Depending on how the internals were implemented in the code you can't change, you may be able to abort part of its execution too.
Outer Thread:
if(oldThread.isRunning())
{
oldThread.interrupt();
// Be careful if you're doing this in response to a user
// action on the Event Thread
// Blocking the Event Dispatch Thread in Java is BAD BAD BAD
oldThread.join();
}
oldThread = new Thread(someRunnable);
oldThread.start();
Inner Runnable/Thread:
public void run()
{
// If this is all you're doing, interrupts and boolean flags may not work
callExternalMethod(args);
}
public void run()
{
while(!Thread.currentThread().isInterrupted)
{
// If you have multiple steps in here, check interrupted peridically and
// abort the while loop cleanly
}
}
Isn't this a little like asking "How can I abort a thread when no method other than Thread.stop() is available?"
Obviously, the only valid answer is Thread.stop(). Its ugly, could break things in some circumstances, can lead to memory/resource leaks, and is frowned upon by TLEJD (The League of Extraordinary Java Developers), however it can still be useful in a few cases like this. There really isn't any other method if the third party code doesn't have some close method available to it.
OTOH, sometimes there are backdoor close methods. Ie, closing an underlying stream that its working with, or some other resource that it needs to do its job. This is seldom better than just calling Thread.stop() and letting it experience a ThreadDeathException, however.
The accepted answer to this question allows you to submit batch work into a background thread. This might be a better pattern for that:
public abstract class dispatcher<T> extends Thread {
protected abstract void processItem(T work);
private List<T> workItems = new ArrayList<T>();
private boolean stopping = false;
public void submit(T work) {
synchronized(workItems) {
workItems.add(work);
workItems.notify();
}
}
public void exit() {
stopping = true;
synchronized(workItems) {
workItems.notifyAll();
}
this.join();
}
public void run() {
while(!stopping) {
T work;
synchronized(workItems) {
if (workItems.empty()) {
workItems.wait();
continue;
}
work = workItems.remove(0);
}
this.processItem(work);
}
}
}
To use this class, extend it, providing a type for T and an implementation of processItem(). Then just construct one and call start() on it.
You might consider adding an abortPending method:
public void abortPending() {
synchronized(workItems) {
workItems.clear();
}
}
for those cases where the user has skipped ahead of the rendering engine and you want to throw away the work that has been scheduled so far.
A thread will exit once it's run() method is complete, so you need some check which will make it finish the method.
You can interrupt the thread, and then have some check which would periodically check isInterrupted() and return out of the run() method.
You could also use a boolean which gets periodically checked within the thread, and makes it return if so, or put the thread inside a loop if it's doing some repetative task and it will then exit the run() method when you set the boolean. For example,
static boolean shouldExit = false;
Thread t = new Thread(new Runnable() {
public void run() {
while (!shouldExit) {
// do stuff
}
}
}).start();
Unfortunately killing a thread is inherently unsafe due to the possibilities of using resources that can be synchronized by locks and if the thread you kill currently has a lock could result in the program going into deadlock (constant attempt to grab a resource that cannot be obtained). You will have to manually check if it needs to be killed from the thread that you want to stop. Volatile will ensure checking the variable's true value rather than something that may have been stored previously. On a side note Thread.join on the exiting thread to ensure you wait until the dying thread is actually gone before you do anything rather than checking all the time.
You appear to not have any control over the thread that is rendering the screen but you do appear to have control of the spinner component. I would disable the spinner while the thread is rendering the screen. This way the user at least has some feedback relating to their actions.
I suggest that you just prevent multiple Threads by using wait and notify so that if the user changes the value many times it will only run the Thread once. If the users changes the value 10 times it will fire off the Thread at the first change and then any changes made before the Thread is done all get "rolled up" into one notification. That won't stop a Thread but there are no good ways to do that based on your description.
The solutions that purpose the usage of a boolean field are the right direction. But the field must be volatile.
The Java Language Spec says:
"For example, in the following (broken) code fragment, assume that this.done is a non-
volatile boolean field:
while (!this.done)
Thread.sleep(1000);
The compiler is free to read the field this.done just once, and reuse the cached value in each execution of the loop. This would mean that the loop would never terminate, even if another thread changed the value of this.done."
As far as I remember "Java Concurrency in Pratice" purposes to use the interrupt() and interrupted() methods of java.lang.Thread.
The way I have implemented something like this in the past is to implement a shutdown() method in my Runnable subclass which sets an instance variable called should_shutdown to true. The run() method normally does something in a loop, and will periodically check should_shutdown and when it is true, returns, or calls do_shutdown() and then returns.
You should keep a reference to the current worker thread handy, and when the user changes a value, call shutdown() on the current thread, and wait for it to shutdown. Then you can launch a new thread.
I would not recommend using Thread.stop as it was deprecated last time I checked.
Edit:
Read your comment about how your worker thread just calls another method which takes a while to run, so the above does not apply. In this case, your only real options are to try calling interrupt() and see if has any effect. If not, consider somehow manually causing the function your worker thread is calling to break. For example, it sounds like it is doing some complex rendering, so maybe destroy the canvas and cause it to throw an exception. This is not a nice solution, but as far as I can tell, this is the only way to stop a thread in suituations like this.
Since you're dealing with code you don't have access to you're probably out of luck. The standard procedure (as outlined in the other answers) is to have a flag that is checked periodically by the running thread. If the flag is set, do cleanup and exit.
Since that option is not available to you, the only other option is to force quit the running process. This used to be possible by calling Thread.stop(), but that method has been permanently deprecated for the following reason (copied from the javadocs):
This method is inherently unsafe. Stopping a thread with Thread.stop causes it to unlock all of the monitors that it has locked (as a natural consequence of the unchecked ThreadDeath exception propagating up the stack). If any of the objects previously protected by these monitors were in an inconsistent state, the damaged objects become visible to other threads, potentially resulting in arbitrary behavior.
More info on this topic can be found here.
One absolute sure way you could accomplish your request (although this is not a very efficient way to do this) is to start a new java process via Runtime.exec() and then stopping that process as necessary via Process.destroy(). Sharing state between processes like this is not exactly trivial, however.
Instead of playing with thread starting and stopping, have you considered having the thread observe the properties that you're changing through your interface? You will at some point still want a stop condition for your thread, but this can be done this was as well. If you're a fan of MVC, this fits nicely into that sort of design
Sorry, after re-reading your question, neither this nor any of the other 'check variable' suggestions will solve your problem.
The correct answer is to not use a thread.
You should be using Executors, see the package: java.util.concurrent
Maybe this can help you: How can we kill a running thread in Java?
You can kill a particular thread by setting an external class variable.
Class Outer
{
public static flag=true;
Outer()
{
new Test().start();
}
class Test extends Thread
{
public void run()
{
while(Outer.flag)
{
//do your work here
}
}
}
}
if you want to stop the above thread, set flag variable to false. The other way to kill a thread is just registering it in ThreadGroup, then call destroy(). This way can also be used to kill similar threads by creating them as group or register with group.

Categories

Resources