I set up a timer to perform a task every 10 seconds within a loop. Also, this is inside a broadcastReceiver, not the MainActivity.
doSomething() {
public void onSuccess(int[] arr) {
for (int i = 0; i<arr.length(); i++) {
<wait 10 seconds>
<show some message>
} // if i == 3, the loop should take 30 seconds to perform
}
}
I tried creating a new thread AND making a timer, but neither solution waits ten seconds for a task inside a loop. I have also tried doing Thread.sleep(10000) without creating a new thread, but this makes the main UI freeze for ten seconds before each task is performed. Could anyone lead me to the right direction?
Edit: this is a possible duplicate of this. My question, in other words, is that is it not possible to do a delayed task inside a loop? If so, why?
try this one count down timer http://developer.android.com/reference/android/os/CountDownTimer.html
Related
I want to make a loop, the times the user wants but with a delay of 3 seconds.
This is the code:
for (i = 0;i < n1; i++){
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
Toast.makeText(KeyMapCreator.this, "Try number " + i,Toast.LENGTH_SHORT).show(); ActionIwantToDo();
}
},3000);
}
The variable i is the one that the user sets.
The problem is that the toast doesn't show up every 3 seconds, it just do like a normal loop without delay. I thought it was because of the time of the toast but if i set the time to 20 secs still being the same.
Someone knows how to make a proper delay inside a loop???
The problem you have is that your loop creates many handlers at once that delay for 3 seconds and then show a toast. They do not wait for each other, and because they are created within milliseconds of each other they will show the toast at the same time.
I'm not sure what you are trying to accomplish, and a loop is probably not what you want. However this is a way to get the toast to display after 3 seconds and every 3 seconds after for a number of times.
For this we will use recursion because it will make it so that you are not blocked on the main thread.
Call doSomething (the recursive function) from where you need the function to start (remember that the second variable is the number of times you want it to run, and 0 is just required as a counter)
doSomething(0, 3)
create doSomething
private void doSomething(int i, int n) {
new Handler().postDelayed(new Runnable() {
#Override
public void run() {
if (i < n) {
Toast.makeText(KeyMapCreator.this, "Try number " + i,Toast.LENGTH_SHORT).show();
actionIWantToDo();
doSomething(i+1, n);
}
}
}, 3000);
}
A Handler just schedules some work for later execution. It doesn't actually block the current thread. All you're doing is scheduling n1 items of work to execute three seconds later, which will all execute in sequence on that exact delay.
You don't really ever want to write code to block the main thread. Ever. It will make your app appear to be unresponsive.
Well, my thread was running only once, so I realized I forgot to put it inside an loop, so I did, put it into an while{true} loop, but still it only repeats once.
Here is my code:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package snake.multiplayer;
import java.util.ArrayList;
/**
*
* #author GUIAKI
*/
public class movimentacoes implements Runnable {
Jogo jogo;
ArrayList<Player> players = new ArrayList<Player>();
int qtdadePlayers;
long lastTime;
long delay;
long millis(){
return System.currentTimeMillis() % 1000;
}
public void run(){
int i;
while(true){
if(lastTime-millis()>=delay){
for(i=0;i<qtdadePlayers;i++){
players.get(i).anda();
System.out.println("Printou");
}
jogo.repaint();
//checaColisao();
lastTime=millis();
}
}
}
}
and here is where I call it:
Mov = new movimentacoes();
Mov.players.add(0,new Player(500,500,playimg.getImage(),15));
Mov.qtdadePlayers=1;
Mov.lastTime=System.currentTimeMillis() % 1000;
Mov.delay=50;
Mov.jogo=this;
Thread t1 = new Thread(Mov);
t1.start();
The most odd thing, is that if I debug the code, it runs repeatedly if I still debug it.
How can I make it keep running?
In the method:
public void run(){
the condition:
if(lastTime-millis()>=delay){
will start to get negative values once it runs more than once, so its needed to change the order:
if(millis()-lastTime>=delay){
Than it all works as it should, thanks Sotirios Delimanolis.
wont lastTime-millis() be a negative value? because millis is time in the future to lastTime
change it to millis()-lastTime
Your code seems ok, there are 2 things that could happen:
1 - for some reasong the thread throws an exception and that would abort the thread
2 - you are running some old version of the compiled code (this could be because the debug version could be in a different folder than the release)
Try to clean and rebuild your project.
What you want to do is to periodically call a Runnable and execute it. You can have a thread run infinitely in a loop and check the time, however this model wastes a lot of CPU time by asking for the time (actually 100% CPU) and even if you include a Thread.sleep() there is no guarantee that it is woken up on time. A much better way is to schedule a task at a fixed rate. Java can do this with the ScheduledExecutorService.
In your case the run method becomes:
public void run(){
for(int i=0;i<qtdadePlayers;i++){
players.get(i).anda();
System.out.println("Printou");
}
jogo.repaint();
}
And then you need to schedule it in an Executor like this:
final ScheduledExecutorService executor = Executors.newScheduledThreadPool(NUM_THREADS); // 1 threads is probably enough for your case
// ...
executor.scheduleAtFixedRate(new Movimentacoes(), 0, delay, TimeUnit.MILLISECONDS);
To stop the Runnable once your program terminates, you call executor.shutdown(). After this call any Runnables currently in progress will receive an interrupted status and no further calls are scheduled. The program will eventually terminate, once all currently still running Runnables have finished their run method. So in case your code takes a while, you might want to query Thread.interrupted().
I'am strugeling with making delays in GWT (client-side).
What I want is to have a break of a few seconds between the iterations of a for-loop.
The first iteration should start instantly, but there has to be a pause between the following ones.
Anyone an idea?
You can delay by using Timer.
Try something like this:
Timer timer = new Timer() {
public void run {
// Whatever code you want to repeat
}
};
for(int i=0; i<10; i++) {
timer.schedule(100) //100 millisecond delay
}
Threading concept could be used for your question
you could try having a counter of loop and check for condition inside loop that if counter is >1 the use thread sleep for some seconds...
I'm trying to perform a task every 5 minute.
The task need to start from: xx:00, xx:05, xx:10, xx:15 and so on so if the time is xx:37 the task will start in xx:40.
I'm used the following code to do that:
Date d1 = new Date();
d1.setMinutes(d1.getMinutes() + 5 - d1.getMinutes()%5);
d1.setSeconds(0);
this.timer.schedule(new Send(), d1, TEN_MINUTES/2);
Send looks like that:
class Send extends TimerTask
{
public void run()
{
if(SomeCondition)
{
Timestamp ts1 = new Timestamp(new java.util.Date().getTime());
SendToDB(ts1);
}
}
}
So the result should be records that if you % the minutes the result would be 0.
But the records time I have is:
*05:35:00
*07:44:40
*07:54:40
*09:05:31
*09:50:00
As you can see the first task start perfectly but then something went wrong.
My guess is that the task calculateds the 5 minute jump after the previous task is finished so the task run time effects, but it's just a guess.
The time a task takes to execute will delay the schedule. From the docs for schedule:
If an execution is delayed for any reason (such as garbage collection or other background activity), subsequent executions will be delayed as well.
You will be better off using scheduleAtFixedRate.
Alternatively, you might try using a simple Thread with a loop to repeatedly perform the task. The last step in the loop can be to sleep the necessary time until you want to start the task again. Assuming that no one iteration of the loop takes five minutes, this will eliminate cumulative delays.
public void run() {
long start = System.currentTimeMillis();
while (shouldRun()) {
doTask();
long next = start + FIVE_MINUTES;
try {
Thread.sleep(next - System.currentTimeMillis());
start = next;
} catch (InterruptedException e) {
. . .
}
}
}
This will start each iteration at the next five-minute interval and will not accumulate delays due to the running time of doTask() or any system delays. I haven't looked at the sources, but I suspect that this is close to what's in Timer.scheduleAtFixedRate.
Why dont you use a Task scheduler or simply a sleep command in a loop which lets the thread sleep for 5 minutes then continue.
An alternative would be to use a Timer class
I would probably make use of ScheduleExecutorService.scheduleAtFixedRate which is a more modern approach than using a Timer and would allow for having multiple worker threads in case there are many tasks being scheduled.
I am using a while loop with a timer.
The thing is that the timer is not used in every loop.
It is used only the first time. After the first time the statements included inside the loop are executed without the delay that i have set.
How is this even possible since the timer is included inside the while loop.
Any solutions ?
int count = 1;
while (count <= 10) {
final Handler handler = new Handler();
Timer t = new Timer();
t.schedule(new TimerTask() {
public void run() {
handler.post(new Runnable() {
public void run() {
// Stuff the while loop executes
}
});
}
}, 20000);
count++;
}
The TimerTask kicks off a new Thread and then the loop proceeds as normal.
The execution of the thread does not cause a delay to the execution of the code in your loop.
It's because you're queueing up 10 toasts all to execute in one hour. Each iteration of your loop takes only a fraction of a millisecond or maybe a tad bit more than that. To enqueue them properly, you could do 3600000 * count instead of 3600000 each time.
This is a terrible way to do it though. You should use AlarmManager for stuff like this.
You're scheduling 10 TimerTasks to execute after an hour, at the same time. So all 10 tasks are being executed after 1 hour, which makes it seem like 1 execute since all the Toast messages display at the same time. To schedule tasks at a fixed delay, with the first task starting in 1 hour, use this method:
Timer t = new Timer();
t.schedule(task, 3600000, 3600000);
This will execute until you call t.cancel().