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.
Related
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.
I'm having some troubles pausing and resuming a method. (Using Java in Eclipse).
Basically I'm writing a program that works a bit like a compiler. I give it a string and it interprets this string, converts it in a block of n commands,conditions and things like loops (depending on the strong) and executes those commands. Like so:
(while
(energy-at-least 1000)
(seq
(move)
(turn clockwise)
)
)
Currently I have a method that stops at the Nth command, but I'm unsure of how to continue after this, since reusing this method and telling it to start at the Nth+1 command mmakes it forget that the program is in loop(s).
Sorry for the poor explanation, but basically I need to be able to stop this method at the Nth command and let it resume from the course it was following. Java had methods for these (resume() and stop() ) but they are deprecated I've seen. Anybody have a good idea?
From what I understand your saying is that you need more fine grained control over the loop in the thread then methods like 'notify', 'resume', etc. are offering. You can do such a thing like this:
The class of the thread could look like this:
public WhateverLoop implements Runnable {
private volatile boolean run = true;
public void run() {
while(run) {
doWhatever();
}
}
public setRun(boolean run) {
this.run = run;
}
}
The 'volatile' part is very important. It enables other threads to influence the 'run' variable (basically it prevents threads copying it into their own memory). Otherwise changes from other threads to the variable won't be visible in the thread.
The controlling class could do this:
WhateverLoop whateverLoop = new WhateverLoop();
Thread WhateverLoopThread = new Thread(whateverLoop);
whateverLoopThread.start();
// Do stuff which consumes time.
...
// Stop the loop
whateverLoop.setRun(false);
In this example I used a boolean, but obviously you can make it as complicated as you want (or not).
An easy way to do this would be to use wait() and notify() methods. Of course, it will depend on how many parallel threads you'll have running since the notify() method cannot guarantee you which thread will actually be awaken.
One way to do this is to represent the execution state in such a way that the subset that is required to resume can be stored in heap objects reachable from a "context" object.
To pause execution, you get the interpretter to record all relevant state in a context object, and return it. To resume, you call the interpretter passing in the previously used context.
This won't work if your interpretter does a recursive walk of the program tree to execute it ...
Another way to do this is to implement "pause" by having the interpretter execute a callback to your CLI (or whatever it is that handles stuff while the program is paused). The CLI "resumes" execution by returning from the callback method.
Have you considered controlling it from a BlockingQueue?
Start it with a queue of N instructions for it to execute. It will pull each instruction from the queue and process it. Once it reaches the Nth instruction it will stop/block. To start it again from where it left off, push more instructions into the queue.
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).
I came across some Java code that has a method containing the following:
static boolean waitForSeconds(long seconds) {
try {
Thread.sleep(seconds * 1000);
} catch (InterruptedException ex) {
return false;
}
return true;
}
What might be the purpose of this? The return value is used to determine whether a computation should continue. It seems strange to me to try to sleep for 1 second for the sole purpose of checking whether the thread was interrupted during that second.
Is the code that calls this method trying to accomplish the same thing as thread.isInterrupted()? Whatever it is trying to do, is there a better way?
The call to waitForSeconds appears at the top of another method, not inside of a loop, so if this code does intend to wait for a second for some purpose in addition to checking for an interrupt, it seems like it would be checking in the wrong place. Wouldn't it be better to put the sleep near the loop, where it is clearer what it is doing?
For the last question, please reply here instead:
Is it clearer to sleep near a function call in a loop or in the function call itself?
The purpose is to pause.
Check the code calling the outer method to try to see why they want to pause.
They may want to save CPU or network.
The purpose of the method is to cause the thread execution to stop for the specified number of seconds. The catch clause allows the method to communicate to the caller that the thread was interrupted, as opposed to the time period expiring.
The idea is probably to introduce a pause in the computation, but if the pause is interrupted, then that means that the computation should not continue. Why a pause is needed is impossible to say without seeing the surrounding (calling) code.
I guess they want to pause for at least x seconds; if for some reason the Thread was unable to sleep that long, they'd use the return value to call the method again
I have a program where I compile java code a user types into a text field, and then run it. A run the code in a seperate thread, so that the GUI they use to input the source code doesn't get locked up.
The GUI has an abort button that should stop the thread. My issue is that I need to stop the compiling thread no matter what is going on inside of it, which means I must account for a case where the thread is caught in an infinite loop (due to user error), and it cannot properly end itself using a safe flag. I've read up on many solutions that involve using a flag of some kind, but they aren't available to me because of this looping issue. I need to have the thread stop and the memory it's using freed (I can't just let it sit in the background forever, unless that is the only solution left). Any advice or alternative solutions? Hopefully some fresh perspectives could help squash this issue.
Edit:
Here's a sample bit of user submitted code:
public class RunMe extends SomethingThatRuns {
public void run() {
int i = 0;
while (i = 0) {
//Prepare to get stuck!
}
}
}
I'll compile this class, and then run it. This is where it will get stuck, and the run() method can never finish, or even loop to check a flag.
You can run it in a new JVM so you can kill it when you want.
Thinking about security this may be a good thing to do too.
Call stop() on the thread.
Yes, this is a deprecated method. However, it really shouldn't be "deprecated", it should be "dangerous." In some circumstances, however, there's really no choice but to use it, and the invocation of an "agent" provided by a user is one of those cases.
Make sure that your program doesn't use any data that are manipulated by this user thread; or, if you do, devise some transactional mechanism to exchange data safely between the threads.
Even this method isn't guaranteed to terminate the thread. For example, the user can catch the resulting Throwable and ignore it. Or, the thread implementation might not respond to stop() calls if the thread is in some native code. But it's your best chance.
The core issue here is the fact that the code even allows an infinite loop to be entered as part of user error. Fix that, and everything else will become easier to deal with.
Properly-behaving threads should usually terminate themselves gracefully when there's no work to do (or return quietly to a thread pool to ask for more work, if that's your application's design). If you feel like you need to have one thread forcefully kill another then you've likely got a fundamental design issue. It's fine to have one thread tell another, "Hey, you should terminate now so that I can join with you..." because that allows your threads to clean things up as they finish. Forcefully destroying threads just isn't the right way to manage these situations.
You can use them to insert a interrputed check in every loop and maybe in other places too.
I can see two options:
As you compile the user code you can edit it before. You may use
ANTLR to parse and modify the code.
There are bytecode manipulation frameworks like ASM that allow you to manipulate code that is already
compiled.
I don't think it is easy but it might be a way.
interupt(); the Thread in the gui
and in the code that the thread runs regularly check for Thread.interrupted() and throw an exception when you do especially inside loops
At a high level, you are asking how one thread might go about stopping another thread. To that end, see this SO question Stopping a Thread in Java?.