Interrupting a java thread gracefully - java

I have written a Java ME puzzle game. I have written the code thus: there is a thread that starts when the app starts, and, once the game has got going, there's a second thread that just runs in an infinite loop -- the main game loop. The second thread looked like this, at one point:
public void run() {
init();
while (shouldIRun) {
updateGameState();
checkUserInput();
updateGameScreen(getGraphics());
this.flushGraphics();
}
}
Lovely. This thread just runs and runs, until I want to kill it, when I just set the boolean shouldIRun to false, whereupon it exits gracefully.
But later on I realised I wanted more. The game is a puzzle game and it's possible for the player to make the wrong moves and then get stuck. When this happens they can fire up a form and select the "restart level" option. A flag restartLevel then gets set, and when the infinite loop gets to the updateGameState() method the level is restarted. But this feels to me like a bit of a gamble -- I don't want to start changing variables of objects being used in the main loop in case of concurrency issues, although I'm probably being paranoid. In practice what I realised I wanted to do was very clear: I simply wanted to pause the infinite loop thread, change the variables to what I wanted, and then restart.
I have done this in the following way:
public void run() {
init();
while (shouldIRun) {
if (shouldIWait) {
iAmWaiting=true;
while (shouldIWait) { };
iAmWaiting=false;
}
updateGameState();
checkUserInput();
updateGameScreen(getGraphics());
this.flushGraphics();
}
}
What I am thinking is the following. If I now want to "pause" this second thread, from the "base" thread, I just set the shouldIWait variable to true, and then just loop until I notice the iAmWaiting variable is also true. I now know for sure that the second thread has paused and I know precisely where it has paused, where by "paused" I actually mean "is stuck in an infinite loop for the time being". I can now goof around with some essential variables, restart the level, and generally sort things out, and then finally set shouldIWait back to false and off we go again.
My question is this: this works fine, for me, but smacks of being a kludge. Is there some completely standard way of doing what is presumably a common thing -- pausing a thread at a given point and then restarting it when I'm ready, which is better than what I'm doing? In particular I suspect that "putting java into an infinite loop" is perhaps not a clever thing to do.

Normally, this is what you would use Object.wait() and Object.notify() for.
There are a couple of ways to implement it for your situation, but here's a simple example:
Object monitor = new Object();
volatile boolean done = false, wait = false;
/* Running on one thread: */
public void run() {
synchronized(monitor) {
while(!done) {
while(wait) {
monitor.wait();
}
gameLogicAndStuff();
}
}
}
/* Running on another thread: */
public void showResetForm() {
wait = true;
synchronized(monitor) {
actuallyShowResetForm();
wait = false;
monitor.notifyAll();
}
}

Maybe it would just be simpler to kill the thread and start a new one with the new level.
If there is some information that needs to be carried from one level to the next, maybe you could refactor your code such that you gather some general information first and then start a thread for each level. (And by starting a thread, I mean using a thread pool.)
I don't think what you are currently doing with busy waiting is evil. As Ben Flynn mentioned in the comments, you could make it semi-busy waiting by looping over Thread.sleep(50).

Related

Java Thread not starting (or taking a long time to start)

I've got a simple (or at least I thought it was) java application that does some work in a Thread.
Something like:
public class Task implements Runnable {
public boolean running = false;
public void run() {
running = true;
// long running processing
}
}
...
void startTask() {
Task task = new Task();
Thread thread = new Thread(task);
thread.start();
// I added this thinking the calling thread might terminate before
// the new thread starts
while (!task.running) {
try {
Thread.sleep(1);
} catch (InterruptedException ie) {
// log error
}
}
startTask() above is called in response to a REST request (this is a Spring Boot application). It runs fine on my dev machine (Windows 10, Oracle JDK), and on an Amazon EC2 instance (Amazon Linux, OpenJDK), but not on a Google Compute instance (Ubuntu 16.04, OpenJDK). In this latter case, the worker thread either never starts (task.running is never set to true), or it sometimes starts after 60+ seconds. I am bewildered.
Given the task itself is not very complex (plus the fact that setting the "running" flag is the first thing it does, and this never happens) leads me to think this is some weird JVM/system-related issue, but I really have no clue.
The most frustrating thing is it works sometimes (usually the first time I upload/run it after a rebuild). And has never failed to work on my PC.
edit: I have tried using the Oracle JRE in Ubuntu, but with the same lack of success.
2nd edit: Yep, I made some mistakes writing the sample code here. Fixed.
Runnable is an interface, so you are creating a new interface called Task! However, you are also providing an implementation for the run() method. This is not going to compile.
Probably, this is what you wanted to do:
class Task implements Runnable {
public boolean running = false;
#Override
public void run() {
running = true;
// long running processing
}
}
Another mistake is that you are calling the thread's run() method directly!
You should call start() instead.
A sample code might look like following:
void startTask() {
Task task = new Task();
Thread thread = new Thread(task);
thread.start();
// I added this thinking the calling thread might terminate before
// the new thread starts
while (!task.running) {
try {
Thread.sleep(1);
}
catch (InterruptedException ie) {
// log error
}
}
}
This is not a way you should start a thread task in Java. In this case you just calling run method. To run thread you should use start method:
thread.start();
You code isn't thread safe, because you access a single variable from multiple threads, because you never used any safe access structure to access this variable, it means that the internal java code optimizer may optimalise your while loop as a while(true) loop.
While you can declare your variable volatile to solve the problem, the real solution would be using Object.wait and Object.notifyAll to handle the waiting period.
After your listener has started the main thread, it should enter a while loop inside a synchronized block that check the condition with wait in between, example:
thread.start();
// I added this thinking the calling thread might terminate before
// the new thread starts
try {
synchronized (task) {
while (!task.running) {
task.wait();
}
}
} catch (InterruptedException ie) {
// log error
}
Then inside your task, you need to set running to true, and then notify all threads.
synchronized (this) {
this.running = true;
this.notifyAll();
}
You also need to mark your running variable as volatile as shown below, otherwise, the other threads will not be guaranteed to see the changes to the running variable.
private volatile boolean running;
Changes to a volatile variable are always visible to other threads
You can look here more about volatile
I think this is a memory model / synchronization problem. You have one thread writing the running flag, and another one reading it without doing any synchronization. This can lead to the reading (in this case main) thread not seeing the updates to running made by the writing (in this case child) thread.
Solutions:
Use synchronized methods to read and update the running flag.
Declare running as volatile.
The most frustrating thing is it works sometimes (usually the first time I upload/run it after a rebuild). And has never failed to work on my PC.
Bugs involving improper synchronization are are notoriously difficult to track down. The root of the problem is that on modern multi-core processors, your code works ... or not ... depending on whether / when memory caches get flushed. This can depend on things like how many physical cores you have, how busy your system is, the behavior of the (OS provided) thread schedule. And when you use a debugger or add traceprints, that is liable to alter the behavior that you are trying to track down.
The best strategy is as follows:
As far as possible use higher-level concurrency functionality provided by the java.util.concurrent.* classes.
Avoid using bare threads, shared variables, mutexes and so on. (They are difficult to use correctly.)
If / when you do need to use the low-level primitives:
make sure that you really understand the Java Memory Model, and
analyse your code very carefully to make sure that it is free of classical race conditions, and memory access hazards.

Android - do task, wait and do nothing, then do task again?

Right now I'm trying to make a function that increases the volume while boolean flag1 == true. So what I want to do is increase volume (I can do this), wait and do nothing ("nop"), then check the flag again.
I've tried doing a while-loop with Thread.sleep() but it gave kinda unreliable behaviour. Keep in mind I'm calling this function from within a service which may have been started more than once, so it's important that I check the flags.
Here's a sample of what I tried:
private void cycleVolume() {
while (flag1 == true) {
mAudioManager.adjustVolume(AudioManager.ADJUST_RAISE, AudioManager.FLAG_PLAY_SOUND);
try {
Thread.sleep(750);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
flag1 becomes false from a BroadcastReceiver event, which should stop executing this function hopefully. However in testing I noticed that this doesn't happen for quite some time after it's supposed to happen, and since I've never done much with Threads before I'm guessing there's an issue there.
So what should I be doing instead?
Thanks.
I'm not sure you're going about this the right way but here is how to fix your current code.
1) Make your flag variable volatile.
2) Provide a synchronized getter and setter method for the flag.
The problem is caused by Java's memory model. Since you have 2 threads accessing the same field you need to provide a way to synchronize their access. Right now, the 2 threads may not see each other's changes to the shared field. For a simple boolean using a volatile is probably more efficient.
Is this code running in its own Thread started from the somewhere in the Service? If you haven't created a separate Thread this is running on the processes main thread and blocking it, which might be leading to your unpredictable results.

What can be the best technique to Terminate the Execution of Program based on some event in Java

I am designing a Card based Game in Java. I have implemented the game logic. It is working fine. Now I want to add a functionality which can check for the time player is playing the game. If the time goes above a threshold limit, I want to terminate the Execution of Game. Please suggest me what should be the best strategy to implement this feature? Is creating a Thread and checking the time a good technique or there is any other technique to achieve this?
Edit: Sorry for the vague description.What I want to implement is, no matter where the player is in the execution sequence, when the time limit reaches, program should terminate. If i implement the check at the looping condition, then if the time is still left, program will continue and complete the set of instructions in the loop, but if the time is over even if the program is entered into the execution loop, it should stop doing whatever it is doing. This is what i want to implement.
Thanks,
Tara Singh
Two possibilities:
If you're using some sort of main loop where all the processing takes place, just add a check for the amount of time passed in there.
You can create a Timer that runs when the time is up and executes some method that ends the game. The timer will take care of creating another thread and executing it for you. Have a look at: http://download.oracle.com/javase/6/docs/api/java/util/Timer.html
I guess checking the elapsed time here and there would be sufficient, but if you want to use threading, here is a simple way to do it. You can also use Timer instead of creating your own thread. The idea is same; TimerTask should interrupt the main thread when the timeout happens.
class Main {
public static void main() throws Exception {
final long timeout_ms = TimeUnit.MINUTES.toMillis(60);
//Store the main thread ref. so the interruption task can use it
final Thread me = Thread.currentThread();
new Thread(){
#Override
public void run(){
// If the timeout happens, or this thread is interrupted
// due to VM termination etc.) interrupt the main thread.
try{
Thread.sleep(timeout_ms);
}catch(InterruptedException e){
//see finally block
}finally{
me.interrupt();
}
}
}.start();
// Executing the game in the main thread.
new Game().run();
}
}
and then
class Game implements Runnable {
#Override
public void run(){
// Basically, check for the interruption flag before you do
// something that takes time to execute.
while(!Thread.currentThread.isInterrupted()){
doSomething();
}
}
}
Using the interruption flag is the preferred way to solve this kind of problem. One of the advantage of using interruption flag instead of creating your own signaling flag, or checking for elapsed time in the loop itself is that you can utilize the interruption support of other APIs.
For example, you might use Thread.sleep() in your game. If you don't use the interruption mechanism, you must wait until sleep() returns. If you do use the interruption mechanism, sleep() will immediately return, throwing InterruptedException, so your app. will be more responsive.
Whenever you catch InterruptedException in your app. handle it as follows unless you have specific reasons:
try{
someMethod();
}catch(InterruptedException e){
//Restore interruption flag
Thread.currentThread.interrupt();
//If you have some clean up to do, do it here.
return;
}
Whenever the app. throws InterruptedException you have to "restore" the interruption flag in order to relay the interruption message up the stack because InterruptedException will "clear" the interruption flag (to false).
How are you keeping the game going in the first place? If, as I suspect it is with some sort of loop then why not allow the loop to terminate given the time condition?

Is my way of doing threads in Android correct?

I'm writing a live wallpaper, and I'm forking off two separate threads in my main wallpaper service. One updates, and the other draws. I was under the impression that once you call thread.start(), it took care of everything for you, but after some trial and error, it seems that if I want my update and draw threads to keep running, I have to manually keep calling their run() methods? In other words, instead of calling start() on both threads and forgetting, I have to manually set up a delayed handler event that calls thread.run() on both the update and draw threads every 16 milliseconds. Is this the correct way of having a long running thread?
Also, to kill threads, I'm just setting them to be daemons, then nulling them out. Is this method ok? Most examples I see use some sort of join() / interrupt() in a while loop...I don't understand that one...
No
No
For #1, I believe your threads are terminating. Once the run() method is left, the thread is considered terminated. If you want the thread to run "forever", you need to repeat your actions.
For #2, the thread will continue running even if you lose all references to it. I would suggest a signal or condition to the worker thread, followed by a join() in the main thread.
Like Yann said, if you keep having to restart your thread(s), it means you are probably not looping correctly.
Say your wallpaper just has a ball moving around the screen, this would be a sample run() method:
boolean isAnimating;
public void run() {
isAnimating = true;
while(isAnimating) {
moveBall();
isAnimating = isWallpaperVisible(); // or whatever conditions apply to not keep animating
}
}
This way your run method will keep running indefinitely.

How can you ensure in java that a block of code can not be interrupted by any other thread

exampl:
new Thread(new Runnable() {
public void run() {
while(condition) {
*code that must not be interrupted*
*some more code*
}
}
}).start();
SomeOtherThread.start();
YetAntherThread.start();
How can you ensure that code that must not be interrupted won't be interrupted?
You can't - at least not with normal Java, running on a normal, non-real-time operating system. Even if other threads don't interrupt yours, other processes might well do so. Basically you won't be able to guarantee that you get a CPU all to yourself until you're done. If you want this sort of guarantee you should use something like Java Real-Time System. I don't know enough about it to know whether that would definitely provide the facility you want though.
The best thing to do is avoid that requirement in the first place.
Assuming you're only concerned with application-level thread contention, and assuming you are willing to fuss with locks as suggested by others (which, IMHO, is a really bad idea), then you should use a ReadWriteLock and not simple object synchronization:
import java.java.util.concurrent.locks.*;
// create a fair read/write lock
final ReadWriteLock rwLock = new ReentrantReadWriteLock(true);
// the main thread grabs the write lock to exclude other threads
final Lock writeLock = rwLock.writeLock();
// All other threads hold the read lock whenever they do
// *anything* to make sure the writer is exclusive when
// it is running. NOTE: the other threads must also
// occasionally *drop* the lock so the writer has a chance
// to run!
final Lock readLock = rwLock.readLock();
new Thread(new Runnable() {
public void run() {
while(condition) {
writeLock.lock();
try {
*code that must not be interrupted*
} finally {
writeLock.unlock();
}
*some more code*
}
}
}).start();
new SomeOtherThread(readLock).start();
new YetAntherThread(readLock).start();
Actually, you can do this if you control the thread instance you are running on. Obviously, there are a ton of caveats on this (like hanging io operations), but essentially you can subclass Thread and override the interrupt() method. you can then put some sort of boolean in place such that when you flip a flag, interrupt() calls on your thread are either ignored or better yet stored for later.
You really need to leave more info.
You cannot stop other system processes from executing unless you run on a real-time OS. Is that what you mean?
You cannot stop garbage collection, etc unless you run a real-time java. Is that what you wanted?
The only thing left is: If you simply want all YOUR other java threads to not interrupt each other because they all tend to access some resource willy-nilly without control, you are doing it wrong. Design it correctly so that objects/data that NEED to be accessed in a synchronized manner are synchronized then don't worry about other threads interrupting you because your synchronized objects are safe.
Did I miss any possible cases?
Using the synchronized approach ( in the various forms posted here ) doesn't help at all.
That approach only helps to make sure that one thread executes the critical section at a time, but this is not what you want. You need to to prevent the thread from being interrupted.
The read/write lock seems to help, but makes no difference since no other thread is attempting to use the write lock.
It only makes the application a little slower because the JVM has to perform extra validations to execute the synchronized section ( used only by one thread , thus a waste of CPU )
Actually in the way you have it, the thread is not "really" being interrupted. But it seems like it does, because it has to yield CPU time to other threads. The way threads works is; the CPU gives to each thread a chance to run for a little while for very shorts periods of time. Even one when a single thread running, that thread is yielding CPU time with other threads of other applications ( Assuming a single processor machine to keep the discussion simple ).
That's probably the reason it seems to you like the thread is being paused/interrupted from time to time, because the system is letting each thread in the app run for a little while.
So, what can you do?
To increase the perception of no interruptions, one thing you can do is assign a higher priority to your thread and decrease it for the rest.
If all the threads have the same priority one possible schedule of threads 1,2,3 could be like this:
evenly distributed
1,2,3,1,2,3,1,2,3,1,2,3,1,2,3,1,2,3
While setting max for 1, and min for 2,3 it could be like this:
More cpu to thread 1
1,1,1,2,1,1,3,1,1,1,2,1,1,1,3,1,2,1,1,1
For a thread to be interrupted by another thread, it has to be in an interruptable state, achieved by calling, Object.wait, Thread.join, or Thread.sleep
Below some amusing code to experiment.
Code 1: Test how to change the priority of the threads. See the patterns on the ouput.
public class Test {
public static void main( String [] args ) throws InterruptedException {
Thread one = new Thread(){
public void run(){
while ( true ) {
System.out.println("eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee");
}
}
};
Thread two = new Thread(){
public void run(){
while ( true ) {
System.out.println(".............................................");
}
}
};
Thread three = new Thread(){
public void run(){
while ( true ) {
System.out.println("------------------------------------------");
}
}
};
// Try uncommenting this one by one and see the difference.
//one.setPriority( Thread.MAX_PRIORITY );
//two.setPriority( Thread.MIN_PRIORITY );
//three.setPriority( Thread.MIN_PRIORITY );
one.start();
two.start();
three.start();
// The code below makes no difference
// because "one" is not interruptable
Thread.sleep( 10000 ); // This is the "main" thread, letting the others thread run for aprox 10 secs.
one.interrupt(); // Nice try though.
}
}
Code 2. Sample of how can be a thread actually be interrupted ( while sleeping in this case )
public class X{
public static void main( String [] args ) throws InterruptedException {
Thread a = new Thread(){
public void run(){
int i = 1 ;
while ( true ){
if ( i++ % 100 == 0 ) try {
System.out.println("Sleeping...");
Thread.sleep(500);
} catch ( InterruptedException ie ) {
System.out.println( "I was interrpted from my sleep. We all shall die!! " );
System.exit(0);
}
System.out.print("E,");
}
}
};
a.start();
Thread.sleep( 3000 ); // Main thread letting run "a" for 3 secs.
a.interrupt(); // It will succeed only if the thread is in an interruptable state
}
}
Before a thread is interrupted, security manager's checkAccess() method is called.
Implement your own security manager, call System.setSecurityManager to install it and make sure it doesn't let any other thread interrupt you while it is in critical section.
Error processing is an example of a use case where it is very useful to stop threads from being interrupted. Say you have a large multi-threaded server and some external condition arises that causes errors to be detected on multiple worker threads simultaneously. Each worker thread generates a notification that an error occurred. Let's say further the desired response is to bring the server to a safe state that will allow it to restart after the error condition is cleared.
One way to implement this behavior is to have a state machine for the server that processes state changes in total order. Once an error notification arrives, you put it into the state machine and let the state machine process it in toto without interruption. This is where you want to avoid interruptions--you want the first notification to cause the error handler to run. Further notifications should not interrupt or restart it. This sounds easy but really isn't--suppose the state machine was putting the server online. You would want to interrupt that to let error processing run instead. So some things are interruptible but others are not.
If you interrupt the error processing thread it may blow the error handler out of the water during synchronized method processing, leaving objects in a potentially dirty state. This is the crux of the problem--thread interrupts go around the normal synchronization mechanism in Java.
This situation is rare in normal applications. However, when it does arise the result can be byzantine failures that are very difficult to anticipate let alone cure. The answer is to protect such critical sections from interrupts.
Java does not as far as I can tell give you a mechanism to stop a thread from being interrupted. Even if it did, you probably would not want to use it because the interrupt could easily occur in low-level libraries (e.g., TCP/IP socket processing) where the effect of turning off interrupts can be very unpredictable.
Instead, it seems as if the best way to handle this is to design your application in such a way that such interrupts do not occur. I am the author of a small state machine package called Tungsten FSM (https://code.google.com/p/tungsten-fsm). FSM implements a simple finite-state machine that ensures events are processed in total order. I'm currently working on a bug fix that addresses exactly the problem described here. FSM will offer one way to address this problem but there are many others. I suspect most of them involve some sort of state machine and/or event queue.
If you take the approach of preventing interruptions it of course creates another problem if non-interruptible threads become blocked for some reason. At that point you are simply stuck and have to restart the process. It does not seem all that different from a deadlock between Java threads, which is in fact one way non-interruptible threads can become blocked. There's really no free lunch on these types of issues in Java.
I have spent a lot of time looking at problems like this--they are very difficult to diagnose let alone solve. Java does not really handle this kind of concurrency problem very well at all. It would be great to hear about better approaches.
Just start your own sub-thread, and make sure that the interrupt calls never filter through to it.
new Thread(new Runnable() {
public void run() {
Thread t = new Thread() {
public void run() {
*code that must not be interrupted*
}
}
t.start(); //Nothing else holds a reference to t, so nothing call call interrupt() on it, except for your own code inside t, or malicious code that gets a list of every live thread and interrupts it.
while( t.isAlive() ) {
try {
t.join();
} catch( InterruptedException e ) {
//Nope, I'm busy.
}
}
*some more code*
}
}
}).start();
SomeOtherThread.start();
YetAntherThread.start();
I think you need to lock on an interrupt flag. What about something like this (not tested):
new Thread() {
boolean[] allowInterrupts = { true };
#Override
public void run() {
while(condition) {
allowInterrupts[0] = false;
*code that must not be interrupted*
allowInterrupts[0] = true;
*some more code*
}
}
#Override
public void interrupt() {
synchronized (allowInterrupts) {
if (allowInterrupts[0]) {
super.interrupt();
}
}
}
}.start();
SomeOtherThread.start();
YetAntherThread.start();
Best halfway solution would be to synchronize all threads on some common object so that no other threads are runnable while you're in the critical section.
Other than that I do not think it's possible. And I'm quite curious as to what kind of problem that requires this type of solution ?
A usual program does not randomly interrupt threads. So if you start a new Thread and you are not passing the reference to this Thread around, you can be quite sure that nothing will interrupt that Thread.
Keep the reference to the Thread private is sufficient in most scenarios. Everything else would be hacky.
Typically work queues like ExecutorService will interrupt their Thread's when asked to do so. In these cases you want to deal with interrupts.

Categories