Delay execution of code in method Java - java

I want to generate random number after every 2 seconds in my java (Android) program continuously for at least 10 minutes. But I just want to pause/delay execution of code in only one method and not the whole program.
I tried using Thread like this -
boolean stop = false;
int random_number = 0;
while(true){
if(stop){ //if stop becomes true, then
return; //terminate the method
}
random_number = Math.random(); //generate random number
//which is used bu some other
//part of code
try {
Thread.sleep(2000); //delay the code for 2 secs
} catch(InterruptedException ex) { //and handle the exceptions
Thread.currentThread().interrupt();
}
}
However, this doesn't work as Thread.sleep stop the whole program execution instead on just stopping execution of code inside method and my whole screen becomes blank.
I also tried using Handler but it didn't work either as it doesn't stop execution of code in my method and instead just stack up.
This will demonstrate the working of it better -
while(true){
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
System.out.println("After 2 secs"); //this gets printed
//later
}
}, 2000);
System.out.println("Before 2 secs"); //this gets printed first
}
So the code stacks up making it equivalent to using while loop and make it incredibly slow.
Also, since I'm developing app for Android, I'm running on Java SE 6, so I can't use scheduleAtFixedRate. Is there any other way in which I can accomplish this?
Thanks a lot!

private Timer timer;
timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
//Generate number
}
}, 2000, 2000);
//Documentation (From SDK)
/**
* Schedule a task for repeated fixed-rate execution after a specific delay
* has passed.
*
* #param task
* the task to schedule.
* #param delay
* amount of time in milliseconds before first execution.
* #param period
* amount of time in milliseconds between subsequent executions.
public void scheduleAtFixedRate(TimerTask task, long delay, long period) {
if (delay < 0 || period <= 0) {
throw new IllegalArgumentException();
}
scheduleImpl(task, delay, period, true);
}
and when you want to stop it
timer.cancel()

Option 1: Using threads, you might run your job off the main (UI) thread:
new Thread(new Runnable() {
// some code here ...
// This might be in a loop.
try {
Thread.sleep(2000);
} catch(InterruptedException ex) {
// Handle ...
}
}
}).start();
Then, if this new thread you'd like to modify UI (i.e. show/hide button, display something on the screen etc), remember to pass that through the UI thread, as only this one can modify the UI. You might consider using Activity.runOnUiThread() for that.
Option 2: Another, more Android-style way of approaching that issue is to use AsyncTask. It contains three callbacks which can be used to do work on- and off- the UI thread. Sketch of such a code could look like:
private class MyTask extends AsyncTask<Void, Void, Void> {
protected Void doInBackground(Void... param) {
// This method is running off the UI thread.
// Safe to stop execution here.
return null;
}
protected void onProgressUpdate(Void... progress) {
// This methid is running on the UI thread.
// Do not stop thread here, but safe to modify the UI.
}
protected void onPostExecute(Long result) {
// Also on UI thread, executed once doInBackground()
// finishes.
}
}
Option 3: Then there is also a Timer, as suggested by #Stultuske. It's less flexible then AsyncTask, but handles the interval for you.

Depending on your needs, you can still accomplish what you seek with Handler.
You don't have to create/start the Handler in a while loop(which, as you noticed, just stacks up unless you stop the loop itself, but it is a nonsense).
Just create the Handler and tell him to post delayed your Runnable instance. In the Runnable at the very end you check your conditions. If it is still OK, then post another runnable delayed, else you do nothing and the Handler will have no more executions.
final Handler handler = new Handler();
Runnable runnable = new Runnable() {
#Override
public void run() {
System.out.println("After 2 secs");
random_number = Math.random();
if (!stop) // should not be stopped, so we add another runnable;
{
handler.postDelayed(this, 2000);
}
}
handler.postDelayed(runnable, 2000);
The only downside is that Handler could freeze if the device is not used for a while, meaning it will start the counting back from where it left once the device screen is turned on.
It could do like 1 minute of correct work, then block at 1.4 seconds when the device is gone in sleep mode, and once it is turned on again, Handler would do the remaining 0.6 seconds.
Still, not knowing your needs you may be unaffected by this behavior and the answer may fit you.

if you want to use thread, do it like this :
Thread t = new Thread(){
public void run(){
while(true){
if(stop) break;
random_number = Math.random();
sleep(2000);
}
}
};
t.start();

Related

Java one code to stop in a loop and not stop the entire program in eclipse

Currently in my brief time with Java I have made a clicker game and I've been trying to implement a way to add a number to an integer (or the int command) every couple of seconds. but whatever I try just stops the entire program completely such as the
Thread.sleep(15000);
wait(15000);
even if they are in a try and catch it just stops the program and not complete a loop every couple of seconds.
If you have Thread.sleep(xxx); in the current thread, then yes, it will stop the current thread for xxx seconds. Because (most likely) Thread.sleep is in the same thread that is controlling the GUI, it is pausing your code from executing, freezing your application. There are two ways you can fix this:
Create a new thread and place the timer code in there:
SwingUtilities.invokeLater will add your Runnable to the queue of threads that AWT executes.
// Because the code is in a different thread, Thread.sleep(1000) will not pause
// the current thread and the application will continue as normal
Thread thread = new Thread(new Runnable() {
int seconds = 0;
#Override
public void run()
{
while (true) {
// wait one second
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
e.printStackTrace();
};
// increment seconds
seconds++;
System.out.println(seconds);
}
}
});
thread.start();
Use an existing timer in the Java API
Look at ScheduledThreadPoolExecutor and its scheduleAtFixedRate method. Here's an example. You could also use a swing timer as mentioned in the comment by Hovercraft Full Of Eels.
To use a Swing timer, you import javax.swing.Timer (not java.util.Timer), create a Timer object with the delay and an action listener listening for when it will fire events, and start it.
Timer timer = new Timer(1000, new ActionListener() {
public void actionPerformed(ActionEvent a)
{
System.out.println("Timer went off!");
}
});
// Repeat every second
timer.start();
Note that this code won't execute on its own; you need to have a GUI running.

Run a process once inside a loop without that process repeating until told to

I have an Android service that is creating quite a bug for me. It is a runnable with an if/else statement. Basically, I need it to continuously run a check and execute the if continuously. It does this flawlessly. I need it the execute the else just one time until it detects the if again.
The problem I have is that it runs the else process in a loop also. How can I make the else statement run once while still detecting for the if?
Heres a code example...
if(mTimer != null) {
mTimer.cancel();
} else {
// recreate new
mTimer = new Timer();
}
// schedule task
mTimer.scheduleAtFixedRate(new TimeDisplayTimerTask(), 0, NOTIFY_INTERVAL);
}
class TimeDisplayTimerTask extends TimerTask {
#Override
public void run() {
// run on another thread
mHandler.post(new Runnable() {
#Override
public void run() {
// display toast
if(musicActive) {
// Set Ringer to vibrate
} else {
// Set Ringer to Normal
}
}
});
}
the problem is that when the service is running and music isnt detected, people are unable to change their ringer setting because my app is still holding it inside the service. If I leave the }else{ empty, I get my desired result, but I need it to run that process one time to set the ringer to normal. I just dont need it to set the ringer to normal once every second.
The simplest way is just to remember, something like this:
boolean lastWasElse = false;
mHandler.post(new Runnable() {
#Override
public void run() {
if(true) {
// do this
lastWasElse = false;
} else if (!lastWasElse) {
// do once and then loop again, but if the answer is still "else" then skip this line.
lastWasElse = true;
}
}
The trouble is where you store the lastWasElse variable - since you are constantly creating new runnables. You need to store one copy of that variable somewhere centrally and check it each time the task runs...
...or re-use the same Runnable constantly instead of creating new ones and store the variable inside the Runnable.
I don't really see why you cant set ringer mode just once, before you start your timer loop :
myAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
// and then
// schedule task
mTimer.scheduleAtFixedRate(new TimeDisplayTimerTask(), 0, NOTIFY_INTERVAL);
More comments:
Your TimerTask#run alread runs in a background thread, you could do your job here without delegating to Handler's thread, which I suppose is the UI thread in your case. In that case make sure you don't have anything potentially blocking UI here :
if(musicActive) {
// do this
// but watch out not to do blocking operations
}
Otherwise, you could only post your // Display Toast to Handler's UI thread and do your if / else in TimerTask#run() directly.

How to prevent if-statement from being executed only once when its condition is first checked?

I have initialized an int variable i = 0. My code has an infinite while loop which is checked immediately when the activity starts. In this loop I need to perform certain tasks after some time interval (e.g. 3 seconds). My code is similar to this:
while(1){
if (System.currentTimeMillis() - learningTime > 3000) {
learningTime = System.currentTimeMillis();
i++;
}
}
Since System.currentTimeMillis() - learningTime > 3000 is true at the beginning of my program execution, i will increment quickly to 1 and later increments will be made every 3 seconds.
How to force i to increment from 0 to 1 in 3 seconds after the activity starts?
Assign to learningTime the System.currentTimeMillis() value so it's 0 > 3000
learningTime = System.currentTimeMillis()
And, anyway you will block the main thread with this code.
That can be an example of Handler
final Handler handler = new Handler();
Runnable runnable = new Runnable() {
#Override
public void run()
{
handler.postDelayed(this, 3000);
}
};
handler.postDelayed(runnable, 3000);
Handler class
Runnable
Handler postDelayed
Anyway, you don't need anymore learningTime and i (?)
You can use a handler to solve this problem so that you don't block the main thread.
I'm not sure if this is the ideal implementation though:
private static final long INTERVAL = 3000;//3 seconds
private Handler handler;
protected void onCreate(Bundle b)
{
super(b);
handler = new Handler();
//post an action to execute after an INTERVAL has elapsed.
handler.postDelayed(new Runnable(){
public void run(){
//do your stuff
doYourStuff();
//post the event again until a stopCondition is met.
if(stopCondition==false){
handler.postDelayed(this,INTERVAL);
}
}
},INTERVAL);
}
As requested in the comments, here is an example of how to use a Handler to delay running some code until a certain amount of time has passed. Define a handler as a variable in your Activity:
Handler handler = new Handler();
Since that handler was created on the UI thread, anything you post to it will also run on the same thread. You can schedule code to run immediately or with a delay. For example:
handler.postDelayed(new Runnable()
{
public void run()
{
//Your code here
}
}, 3000); //Code will be scheduled to run on the UI thread afer 3 seconds

Android - run a function every X milliseconds while condition true?

I just want to run a function myFunction() every X milliseconds while an external flag is true. However I've had no luck with Threads (app crashes), Timers (app crashes). Handlers/runnables are a bit better but typically I'll have something like:
Runnable rr = new Runnable() {
public void run() {
if (flag1 == true) {
myFunction();
} else {
return;
}
}
};
handler.postDelayed(rr, 1000);
But then the problem is execution will come one after another after 1000 milliseconds. I want one execution of myFunction to happen, wait 1000ms, call myFunction, wait 1000ms, call myFunction, etc, until flag1 becomes false.
I've been stuck on this for a while, so any help is much appreciated.
EDIT - more question info
The handler is defined as follows:
private Handler handler = new Handler();
And its class is a BroadcastReceiver where I'm trying to listen for flag changes based on asynchronous events from external hardware.
This will loop and check the flag every second for the lifetime of the application.
Thread myThread = new Thread(new UpdateThread());`
myThread.start();`
public class UpdateThread implements Runnable {
#Override
public void run() {
while(true)
{
if (flag1 == true)
myFunction();
myThread.sleep(1000);
}
}
also you may want to look at a service
http://developer.android.com/reference/android/app/Service.html

Problems with runnable

I was advised to use this code to make my method execute after a definite period of time, i modified it a bit and now I have:
private Handler mHandler = new Handler();
private Runnable mUpdateTimeTask = new Runnable() {
public void run() {
final long start = mStartTime;
// Get the difference in ms
long millis = SystemClock.uptimeMillis() - start;
// Format to hours/minutes/seconds
int mTimeInSec = (int) (millis / 1000);
// Do your thing
Location location = tracker.getLastKnownLocation(best);
RetrieveAvgPower(location);
// Update at the next second
mHandler.postAtTime(this, 1000);//start + ((mTimeInSec + 10) * 1000));
}
};
And I try to start and stop it with:
public void onClick(View v) {
switch (v.getId()) {
case R.id.start:
mStartTime = System.currentTimeMillis();
mHandler.removeCallbacks(mUpdateTimeTask);
mHandler.postDelayed(mUpdateTimeTask, 1000);
break;
case R.id.stop:
mHandler.removeCallbacks(mUpdateTimeTask);
break;}}
However, there is an issue. First of all, my method sets text and writes a line to log file, but if I use the code above text is not being set, however all info is being written to log file automatically. Another thing is i can't stop runnable - after it starts executing program seems to be not responding and crashes if I try to press stop button. What am I doing wrong and how it can be solved?
Shouldn't the last line of run() call Handler.postDelayed() rather than Handler.postAtTime()?
Depending on how event queues are implemented in Android you might be killing the thread by using the wrong one... you're basically repeatedly setting a Runnable to run at 1 second after the thread originally started, so no other events get to run.
To stop your runnable you can just add something like this:
class A implements Runnable
{
private volatile boolean runTask = false;
public void run()
{
runTask = true;
while(runTask)
{
// Do your thing
Thread.sleep(1000); // wait 1 second before "Do your thing" again
}
}
public void stop()
{
runTask = false;
}
}
As for the text not updating I didnt understand very well, is it in a swing gui that is not setting?
EDIT
Added a Thread.sleep(1000) at the end of the run method
EDIT by peer:
Moved the Thread.Sleep(1000) so that the Runnable will run once a second until stopped (instead of running continuously and then waiting 1 second after being stopped).

Categories