Reputation: 1051
I have a method, wich supposed to interrupt a thread, but it's not. Do I need to always check the thread interrupted in the while method to stop the thread? How can I just terminate the thread at anytime?
solverTh = new Thread(new Runnable() {
@Override
public void run() {
while(somethingistrue){
//do lot of stuff here for long time
}
}
});
solverTh.start();
}
public void terminate(){
if(solverTh != null){
solverTh.interrupt();
}
}
okay than I thought the "lot of stuff" is irrelevant, but I will post it than. It makes openGL operations, I added the boolean variable "terminated" to the code it works now, I just wanted to find a nicer solution: (glc is a GLCanvas, and the rotmultiplecube method rotates 3 objects) Anyways I've solved the problem now, thanks for the answers.
terminated = false;
try {
Thread.sleep(2000);
} catch (InterruptedException ex) {
Logger.getLogger(BruteForce.class.getName()).log(Level.SEVERE, null, ex);
}
int colorToBeSolved = Statics.RED_BLUE_TABLE[stateToBeSolved];
System.out.println(stateToBeSolved + "," + colorToBeSolved);
if(entities[0].getColor() != colorToBeSolved){
if(terminated) return;
fullRotate(Statics.FIRST_ROW, Statics.DOWN);
}
if(entities[1].getColor() != colorToBeSolved){
if(terminated) return;
fullRotate(Statics.SECOND_COL, Statics.RIGHT);
}
if(entities[2].getColor() != colorToBeSolved){
if(terminated) return;
fullRotate(Statics.THIRD_COL, Statics.RIGHT);
}
if(entities[3].getColor() != colorToBeSolved){
if(terminated) return;
fullRotate(Statics.SECOND_ROW, Statics.DOWN);
}
if(entities[6].getColor() != colorToBeSolved){
if(terminated) return;
fullRotate(Statics.THIDR_ROW, Statics.DOWN);
}
for(int i = 0; i < 9; ++i){
int col = i % 3;
int row = 3 + i/3;
while(entities[i].getState() != stateToBeSolved){
for(int j = 0;j < 2; ++j){
if(entities[i].getState() != stateToBeSolved){
if(terminated) return;
fullRotate(col, Statics.LEFT);
if(terminated) return;
fullRotate(row, Statics.UP);
if(terminated) return;
fullRotate(col, Statics.RIGHT);
if(terminated) return;
fullRotate(row, Statics.DOWN);
}
}
for(int j = 0;j < 2; ++j){
if(entities[i].getState() != stateToBeSolved){
if(terminated) return;
fullRotate(col, Statics.RIGHT);
if(terminated) return;
fullRotate(row, Statics.UP);
if(terminated) return;
fullRotate(col, Statics.LEFT);
if(terminated) return;
fullRotate(row, Statics.DOWN);
}
}
}
}
}
and the fullrotate method:
private void fullRotate(int selectionIndex, int direction){
for(int i = 0; i < 9; ++i){
glc.rotMultipleCubeSlow(selectionIndex, direction);
try {
Thread.sleep(20);
} catch (InterruptedException ex) {
terminate();
}
}
glc.setMovesText(selectionIndex, direction);
glc.setMultipleStateAndColorsByTable(selectionIndex, direction);
glc.isEntitiesRight();
}
Upvotes: 1
Views: 392
Reputation: 706
The elegant solution is to modify your fullRotate() method to throw InterruptedException.
private void fullRotate(int selectionIndex, int direction)
throws InterruptedException{
for(int i = 0; i < 9; ++i){
glc.rotMultipleCubeSlow(selectionIndex, direction);
Thread.yield();
}
glc.setMovesText(selectionIndex, direction);
glc.setMultipleStateAndColorsByTable(selectionIndex, direction);
glc.isEntitiesRight();
}
Your thread run() then becomes:
solverTh = new Thread(new Runnable() {
@Override
public void run() {
while(somethingistrue &&
!Thread.currentThread().isInterrupted()) {
try {
//do lot of stuff here for long time
} catch (InterruptedException ex) {
// handle stop processing
}
}
}
});
solverTh.start();
Also you have to remove the try catch from the following:
try {
Thread.sleep(2000);
} catch (InterruptedException ex) {
Logger.getLogger(BruteForce.class.getName()).log(Level.SEVERE, null, ex);
}
Upvotes: 1
Reputation: 24857
The only thing that can reliably stop the execution of one thread from another is the OS. So, there are not many choices:
1) Signal the thread to stop itself. This scheme kinda depends on what the thread is doing. If it's running on another processor or stuck on a blocking call you cannot unblock, (note-many blocking calls can be persuaded to return early), there can be problems.
What is 'lot of stuff' doing?
2) Use an OS call to terminate the thread. This can be a viable option, depending on what the thread does. If there is any possibility of terminating the thread while it holds a public lock on a vital resource, (eg. it's in the middle of a malloc() and has the memory-manager locked), then you can get into trouble. You have to be sure of what thread is doing to safely abort it in this way.
3) Use a separate process to run the 'stuff'. This will obviously work OK, but usually involves slow and painful inter-process comms to pass data and return results.
4) Design the app so that it does not need to terminate the thread. Some apps never need to terminate any threads except at app shutdown, so there's no problem - the OS can stop anything. In those cases where a thread must be 'stopped' during an app run and is running a lengthy CPU-intensive operation or is blocked for a long and possibly indeterminate period, 'orphaning' a thread by setting its priority to minimum/idle and just leaving it to eventually die off is another common approach.
The worst possible scenario is a thread running a lot of stuff for long time that uses the memory-manager or other public locks, possibly in a library where you don't know exactly what it's doing, can't be hooked and reads/writes data in such a way that 'orphaning' it off means that another thread cannot be started to use the data. You're really stuft then and you may have to terminate the app and restart. It's just best to avoid designs where a thread can get into such a state :)
5) Forgot one - if the thread is using data you can get at, setting something to NULL, 0, MaxInt or some other like bodge can cause an exception to be raised in the thread running the long stuff. When execution bubbles out of long stuff, the thread can check the Interrupted state in the exception handler and exit if set.
Upvotes: 0
Reputation: 7523
When a thread is running ( consuming CPU cycles ) , then it will not by default ( automatically ) respond to Thread.interrupt()
. You will have to write the code to do this explicitly.
Break up //do lot of stuff here for long time
into 2 or more steps , and insert between these steps checks for the Thread.currentThread().isInterrupted()
- if true - break out , else continue. This is only safe way to achieve what you want.
It depends on what the long running stuff is, you will have to design the steps and decide when its best to check for interruption and breakout.
Upvotes: 0
Reputation: 423
while(somethingistrue !Thread.currentThread().isInterrupted()){
//do lot of stuff here for long time
}
Does not have to work for blocking IO. Use dirty tricks: override Thread.interrupt() close IO object, cause IOException that if properly handled may end thread run method.
Upvotes: 2
Reputation: 1543
The only way to interrupt thread is to make it exit itself. Strightforward interruption is not even implemented in Java because of deadlocks possibility. So your thread code must look like:
solverTh = new Thread(new Runnable() {
@Override
public void run() {
while(somethingistrue)
// Do a little stuff here
}
}
});
solverTh.start();
And somethingistrue
is a kind of a signal for thread to interrupt.
Upvotes: 0