Java Suitable Multithreading Implementation? - java

I'm very new to multithreading - I've done a few hours of research and tested a few different ways. I've recently implemented this code:
public class resetDataThread implements Runnable {
VertexHashMap allVertices;
public resetDataThread(VertexHashMap allVertices){
this.allVertices = allVertices;
}
#Override
public void run() {
for (int i = 0; i < allVertices.data.length; i++)
{
if (allVertices.data[i] != null){
allVertices.data[i].inClosed = false;
allVertices.data[i].inOpen = false;
}
}
System.out.println("Thread Finished!");
}
}
Please note, VertexHashMap is a self implemented hash map that stores Vertices.
Runnable r = new resetDataThread(allVertices);
Thread t1 = new Thread(r);
I call the method like so:
t1.run();
This line of code gets called many times without creating new instances of r or t1.
My reason for implementing this is so my program can fetch new data and output results while it resets the storage's boolean variables (allVertices). My main aim is execution speed of my program, so I figured I could multi thread this section of code.
So my question is, is this safe, suitable or a good way to do this?
Example
...code that changes allVertices variables
t1.run(); //this will run while otherSectionOfProgram and yetAnotherSectionOfProgram is executed
otherSectionOfProgram();
yetAnotherSectionOfProgram();
The example above can be called many times however the contents of allVertices will always be the same (except for the boolean settings), so I'm just wanting to make sure it's okay to use the run() method the way I have - as I want to ensure I practise good java/programming.

If what you're after is to have a single background thread running then call t1.start() to start a background thread.
If you want to get more advanced with creating threads look into the Executor Service for java Java Executor Service
It's also worth noting that unless allVertices is pretty large in size it shouldn't take much time to run the run() method anyway, but it's easy enough to time it to see how much difference it makes.
EDIT:
Also make sure otherSectionOfProgram(); and yetAnotherSectionOfProgram(); do not modify allVertices if you aren't creating a new instance of that because your background thread will be operating on it as well.

t1.run();
This line of code gets called many times
Call start() on your thread, not run().
What's the difference between Thread start() and Runnable run()

You start created threads with t.start() method, t.run() won't start a new thread.
Also, calling t.start() multiple times still won't create a new thread each time it's called, your thread t is unusable(dead) after it's done once. You need to create new Thread for every ... well... thread.

For starting new thread you should call start() method.
For program safety, you should take care about mutual exclusion, I should know logic of program to advise you more about the correct solution, but you may want synchronize allVertices if another sections of program may change it simultaneously or if you want to create more than one instance of your thread:
#Override
public void run() {
synchronized(allVertices){
for (int i = 0; i < allVertices.data.length; i++)
{
if (allVertices.data[i] != null){
allVertices.data[i].inClosed = false;
allVertices.data[i].inOpen = false;
}
}
}
System.out.println("Thread Finished!");
}

OK, first of all, calling Thread.run() will not start a new Thread. It will run the method on the calling thread. To actually start a new thread you have to use Thread.start(). In the code you posted there is no multithreading happening.
Secondly, the line VertexHashMap is a self implemented hash map that stores Vertices. screams non-thread-safe to me. You know there is a special ConcurrentHashMap version of HashMap to deal with concurrent (i.e. multithreaded) use? Which structure did you base your class on? Did you make your own objects thread-safe? Inter-thread visibility problems may arise.
Thirdly, reusing threads is tricky business. Just calling run multiple times won't even make a single Thread, but calling start more than once will throw an exception. As some of the other answers pointed out - using an ExecutorService is a great alternative - you can set it up to use whatever number of threads you want (and have flexibility in how it behaves under load), and have it reuse its threads (instead of re-inventing the complex machinery behind it).
Finally - you may want to think about visibility of your objects. In your case you have the VertexHashMap as default visibility. This means that other classes can see and use it directly. This may be a problem if, for example, you are in the process of clearing it, or re-populating. Then the user gets a half-ready object, whose methods may easily fail. Java has a Future interface just for that - it's an interface to be used with multithreading that "promises" to return a ready object. It's the basis for Swings SwingWorker and Androids AsyncTask - objects that do tasks in the background thread, and then return ready results to the foreground for further use.

Related

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.

Why can't a Java Thread object be restarted?

I know that it is not possible to restart a used Java Thread object, but I don't find an explanation why this is not allowed; even if it is guaranteed that the thread has finished (see example code below).
I don't see why start() (or at least a restart()) method should not be able to somehow reset the internal states - whatever they are - of a Thread object to the same values they have when the Thread object is freshly created.
Example code:
class ThreadExample {
public static void main(String[] args){
Thread myThread = new Thread(){
public void run() {
for(int i=0; i<3; i++) {
try{ sleep(100); }catch(InterruptedException ie){}
System.out.print(i+", ");
}
System.out.println("done.");
}
};
myThread.start();
try{ Thread.sleep(500); }catch(InterruptedException ie){}
System.out.println("Now myThread.run() should be done.");
myThread.start(); // <-- causes java.lang.IllegalThreadStateException
} // main
} // class
I know that it is not possible to
restart a used Java Thread object, but
I don't find an explanation why this
is not allowed; even if it is
guaranteed that the thread has
finished (see example code below).
My guestimation is that Threads might be directly tied (for efficiency or other constrains) to actual native resources that might be re-startable in some operating systems, but not in others. If the designers of the Java language had allowed Threads to be re-started, they might limit the number of operating systems on which the JVM can run.
Come to think of it, I cannot think of a OS that allows a thread or process to be restarted once it is finished or terminated. When a process completes, it dies. You want another one, you restart it. You never resurrect it.
Beyond the issues of efficiency and limitations imposed by the underlying OS, there is the issue of analysis and reasoning. You can reason about concurrency when things are either immutable or have a discrete, finite life-time. Just like state machines, they have to have a terminal state. Is it started, waiting, finished? Things like that cannot be easily reasoned about if you allow Threads to resurrect.
You also have to consider the implications of resurrecting a thread. Recreate its stack, its state, is is safe to resurrect? Can you resurrect a thread that ended abnormally? Etc.
Too hairy, too complex. All that for insignificant gains. Better to keep Threads as non-resurrectable resources.
I'd pose the question the other way round - why should a Thread object be restartable?
It's arguably much easier to reason about (and probably implement) a Thread that simply executes its given task exactly once and is then permanently finished. To restart threads would require a more complex view on what state a program was in at a given time.
So unless you can come up with a specific reason why restarting a given Thread is a better option than just creating a new one with the same Runnable, I'd posit that the design decision is for the better.
(This is broadly similar to an argument about mutable vs final variables - I find the final "variables" much easier to reason about and would much rather create multiple new constant variables rather than reuse existing ones.)
Because they didn't design it that way. From a clarity standpoint, that makes sense to me. A Thread represents a thread of execution, not a task. When that thread of execution has completed, it has done its work and it just muddies things were it to start at the top again.
A Runnable on the other hand represents a task, and can be submitted to many Threads as many times as you like.
Why don't you want to create a new Thread? If you're concerned about the overhead of creating your MyThread object, make it a Runnable and run it with a new Thread(myThread).start();
Java Threads follow a lifecycle based on the State Diagram below. Once the thread is in a final state, it is over. That is simply the design.
You can kind of get around this, either by using a java.util.concurrent.ThreadPoolExecutor, or manually by having a thread that calls Runnable.run() on each Runnable that it is given, not actually exiting when it is finished.
It's not exactly what you were asking about, but if you are worried about thread construction time then it can help solve that problem. Here's some example code for the manual method:
public class ReusableThread extends Thread {
private Queue<Runnable> runnables = new LinkedList<Runnable>();
private boolean running;
public void run() {
running = true;
while (running) {
Runnable r;
try {
synchronized (runnables) {
while (runnables.isEmpty()) runnables.wait();
r = runnables.poll();
}
}
catch (InterruptedException ie) {
// Ignore it
}
if (r != null) {
r.run();
}
}
}
public void stopProcessing() {
running = false;
synchronized (runnables) {
runnables.notify();
}
}
public void addTask(Runnable r) {
synchronized (runnables) {
runnables.add(r);
runnables.notify();
}
}
}
Obviously, this is just an example. It would need to have better error-handling code, and perhaps more tuning available.
If you are concerned with the overhead of creating a new Thread object then you can use executors.
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
public class Testes {
public static void main(String[] args) {
Executor executor = Executors.newSingleThreadExecutor();
executor.execute(new Testes.A());
executor.execute(new Testes.A());
executor.execute(new Testes.A());
}
public static class A implements Runnable{
public void run(){
System.out.println(Thread.currentThread().getId());
}
}
}
Running this you will see that the same thread is used for all Runnable objects.
A Thread is not a thread. A thread is an execution of your code. A Thread is an object that your program uses to create and, manage the life-cycle of, a thread.
Suppose you like playing tennis. Suppose you and your friend play a really awesome set. How would your friend react if you said, "That was incredible, let's play it again." Your friend might think you were nuts. It doesn't make sense even to talk about playing the same set again. If you play again you're playing a different set.
A thread is an execution of your code. It doesn't make sense to even talk about "re-using" a thread of execution for same reason that it makes no sense to talk about re-playing the same set in tennis. Even if another execution of your code executes all the same statements in the same order, it's still a different execution.
Andrzej Doyle's asked, "Why would you want to re-use a Thread?" Why indeed? If a Thread object represents a thread of execution---an ephemeral thing that you can't even talk about re-using---then why would you want or expect the Thread object to be re-useable?
i've been searching the same solution which you seem to be looking for, and i resolved it in this way. if you occur mousePressed Event you can terminate it also reuse it, but it need to be initialized, as you can see below.
class MouseHandler extends MouseAdapter{
public void mousePressed(MouseEvent e) {
if(th.isAlive()){
th.interrupt();
th = new Thread();
}
else{
th.start();
}
}
}

Java: Is it common practice to create a new Thread when a lock is held?

I've got a question related but not identical to my first question ever here:
Java: what happens when a new Thread is started from a synchronized block?
Is it a common practice to create and start() a new Thread when you're holding a lock?
Would that be a code smell?
Basically I've got a choice between doing this:
public synchronized void somemethod() {
(every time I find a callback to be notified I start a thread)
Thread t = new Thread( new Runnable() {
void run() {
notifySomeCallback();
}
}
t.start();
...
(lengthy stuff performed here, keeping the lock held)
...
}
or this:
public void somemethod() {
(create a list of callbacks to be notified)
synchronized(this){
(potentially add callbacks)
...
(lengthy stuff performed here, keeping the lock held)
...
}
(notify the callbacks without holding a lock and once
we know the lock has been released)
}
I think the latter is better but I wanted to know if there
are cases where the first option would be ok? Do you sometimes
do that? Have you seen it done?
answer3:
You should always hold on to a lock as short as possible. So only the resource which is potentially referenced to from multiple threads should be locked for the smallest amount of time when the chance of a 'corrupt' resource exists (e.g. the writer thread is updating the resource)
Don't spin off a thread for every little thing which needs to be done. In the case of your callback threads, have 1 callback thread work off a queue of things to do.
You are aware that the two code snippets will result in different execution orders.
The first one will run the callbacks asynchronously, while the lengthy stuff is being performed. The second one will finish doing the lengthy stuff first and then call the callbacks.
Which one is better depends on what the callbacks need to do. It might well be a problem if they need lengthy stuff to be done first.
Who is waiting on the lock?
If the callbacks need the lock to run, it makes little sense to fire them, while you still hold the lock. All they would do is just wait for lengthy stuff to be done anyway.
Also, in the first snippet, you have one thread per callback. The second snippet is not explicit, but if you have only one thread for all of them, this is another difference
(whether the callbacks run simultaneously or in sequence). If they all need the same lock, you might as well run them in sequence.
If you want to run many callbacks with one or more threads, consider using an Executor instead of managing the threads yourself. Makes it very easy to configure an appropriate number of threads.
It depends on whether or not you want the callbacks to be executed concurrently with the lengthy stuff or not. If we are talking about a Swing GUI, option 1 is not good, because you shouldn't do Swing operations in several concurrent threads, so I propose the following:
public void somemethod() {
Thread t = new Thread( new Runnable() {
void run() {
doLengthyStuff();
}
}
t.start();
(notify the callbacks)
}

Prevent Swing GUI locking up during a background task

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.

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