I want to execude some code every second in android, but I'd like to do is in one thread (main thread). So far I have this:
locationTimer = new Timer("locationTimer", false);
locationTimer.schedule(new LocationCheckerTask(this), 0, 1000);
public class LocationCheckerTask extends TimerTask {
private GeoWatcher watcher;
public LocationCheckerTask(Context context) {
watcher = new GeoWatcher(context);
}
#Override
public void run() {
// funky stuff
}
}
Unfortunately, Timer class runs it's tasks on another thread.
Why I want to do this in a single thread?
Code in run() method will be executing really fast, so I figured I don't need another thread for it. What I want to do is to construct separate threads in run() method based on condition calculated every second. So instead of having child thread constructing another threads, I'd like to do this on the main one.
You can do this with Handler
public class Job implements Runnable{
private Handler handler;
public Job () {
handler = new Handler(Looper.getMainLooper());
loop();
}
#Override
public void run() {
// funky stuff
loop();
}
private void loop() {
handler.postDelayed(this, 1000);
}
}
use runOnUiThread(Runnable) method of Activity to run the task in UI Thread
public class LocationCheckerTask extends TimerTask {
private GeoWatcher watcher;
public LocationCheckerTask(Context context) {
watcher = new GeoWatcher(context);
}
#Override
public void run() {
runOnUiThread(new Runnable() {
#Override
public void run() {
// funky stuff
}
});
}
}
the Handler is a perfect candidate for such tasks (dont try to combine TimerTask + runOnUiThread - it is useless as it uses a Handler under the hood)
private Runnable fiveSecondRunnable = new Runnable() {
#Override
public void run() {
if (count5 < 0) {
switchT030Sec();
} else {
tvSec5.setText(""+count5);
Log.v("5sec set", "yes");
count5--;
man.postDelayed(this, 1000);
}
}
};
and start it by calling
man.post(fiveSecondRunnable);
Related
I have a class like this Render:
public class Render {
private Timer timer;
private TimerTask timerTask;
#Override
public void refresh() {
if (timerTask != null)
timerTask.cancel();
timerTask = new LoadTask();
timer.schedule(timerTask, 1000);
}
private class LoadTask extends TimerTask {
#Override
public void run() {
//request the server
}
}
}
The refresh method may be called very frequently, but the job to be done inside the refresh is a little heavy, it have to request something from the server, so I tried to make this method execute after a delay.
But as shown, a new LoadTask instance will be created once this method got called, is this a waste of memory in android?
So I wonder if any idea to fix it?
You will try this one to execute the task with the delay
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
#Override
public void run() {
//Your task it will execute at 1 time only...
}
}, 5000);//5 seconds delay and you can change the delay time...
It will execute the thread at ever 10 seconds like as a loop function...
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
//Your logic it will repeating you task ever 10 seconds....
}
}, 5000, 5000);
Why dont you just initialise the TimerTask in the constructor of Render Class. Like this
public class Render {
private Timer timer;
private TimerTask timerTask;
public Render()
{
timerTask = new LoadTask();
}
//....
}
And then just use the reference in Refresh function. This should solve your problem :)
You can use the java Executors, included in version 7. You reuse the thread instance and the LoadTask instance.
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
public class Render {
private final LoadTask yourDelayedTask;
private ScheduledExecutorService scheduler;
private static final long DELAY_MS = 1000;
public Render() {
scheduler = Executors.newScheduledThreadPool(1);
yourDelayedTask = new LoadTask();
}
private ScheduledFuture<?> lastScheduledTask;
public void refresh() {
if (lastScheduledTask != null && !lastScheduledTask.isCancelled() || !lastScheduledTask.isDone()) { // Review this logic
lastScheduledTask.cancel(true);
}
lastScheduledTask = scheduler.schedule(yourDelayedTask, DELAY_MS, TimeUnit.MILLISECONDS);
}
private class LoadTask implements Runnable {
#Override
public void run() {
// request the server
}
}
}
I have called a method in ServletContextListener as thread ..Now as per my need i have to delay the thread for 1 minutes and then start executing the method called in the thread but i am not able to do that as i am very new in this...
Here is my code ...
public class Startup implements ServletContextListener {
#Override
public void contextDestroyed(ServletContextEvent sce) {
}
public void contextInitialized(ServletContextEvent sce) {
// Do your startup work here
System.out.println("Started....");
//captureCDRProcess();
new Thread(new Runnable() {
#Override
public void run() {
captureCDRProcess();
}
}).start();
}
Please help me ..
Thanks in advance..
To do this properly, you need to use a ScheduledThreadPoolExecutor and use the function schedule like this:
final ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(NUM_THREADS);
executor.schedule(new Runnable() {
#Override
public void run() {
captureCDRProcess();
}
}, 1, TimeUnit.MINUTES);
Thread.sleep is not the way to go, because it does not guarantee that it wakes up after a minute. Depending on the OS and the background tasks, it could be 60 seconds, 62 seconds or 3 hours, while the scheduler above actually uses the correct OS implementation for scheduling and is therefore much more accurate.
In addition this scheduler allows several other flexible ways to schedule tasks like at a fixed rate or fixed delay.
Edit: Same solution using the new Java8 Lamda syntax:
final ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(NUM_THREADS);
executor.schedule(() -> captureCDRProcess(), 1, TimeUnit.MINUTES);
Or you can delay creating the thread with Timer and TimerTask:
public void contextInitialized() {
// Do your startup work here
System.out.println("Started....");
Timer timer = new Timer();
TimerTask delayedThreadStartTask = new TimerTask() {
#Override
public void run() {
//captureCDRProcess();
//moved to TimerTask
new Thread(new Runnable() {
#Override
public void run() {
captureCDRProcess();
}
}).start();
}
};
timer.schedule(delayedThreadStartTask, 60 * 1000); //1 minute
}
Have a look at Thread.sleep(). Maybe add it to the new thread's run method, so that it sleeps the needed time before doing any meaningful work.
You can start thread and inside the thread use sleep method for one minute.
ScheduledThreadPoolExecutor has this ability, but it's quite heavyweight.
Here's a simple implementation with a test (signature close to Android's Handler.postDelayed()):
public class JavaUtil {
public static void postDelayed(final Runnable runnable, final long delayMillis) {
final long requested = System.currentTimeMillis();
new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
long leftToSleep = requested + delayMillis - System.currentTimeMillis();
if (leftToSleep > 0) {
Thread.sleep(leftToSleep);
}
break;
} catch (InterruptedException ignored) {
}
}
runnable.run();
}
}).start();
}
}
Test:
#Test
public void testRunsOnlyOnce() throws InterruptedException {
long delay = 100;
int num = 0;
final AtomicInteger numAtomic = new AtomicInteger(num);
JavaUtil.postDelayed(new Runnable() {
#Override
public void run() {
numAtomic.incrementAndGet();
}
}, delay);
Assert.assertEquals(num, numAtomic.get());
Thread.sleep(delay + 10);
Assert.assertEquals(num + 1, numAtomic.get());
Thread.sleep(delay * 2);
Assert.assertEquals(num + 1, numAtomic.get());
}
I am modifying the following code in my activity:
new Handler().postDelayed(new Runnable() {
public void run() {
txtStatus.setText("hello");
}
}, 1000);
to:
static Runnable myRunnable = new Runnable() {
public void run() {
txtStatus.setText("hello");
};
new Handler().postDelayed(myRunnable, 1000);
Which obviously doesn't work, since we're referencing a non static variable.
This doesn't work either:
public void setText() {
txtStatus.setText("hello");
}
static Runnable myRunnable = new Runnable() {
public void run() {
setText(); // doesn't work
MyActivity.this.setText(); // still doesn't work
};
new Handler().postDelayed(myRunnable, 1000);
so how would my initial example be rewritten to use a static class instead of an anonymous inner class (to avoid the potential of a memory leak)?
You can use WeakReference to avoid memory leak problems. Here is some code, which illustrate this idea
public static class MyRunnable implements Runnable {
private WeakReference<Activity> activityRef;
public MyRunnable(Activity activity) {
activityRef = new WeakReference<Activity>(activity);
}
public void run() {
//some code
}
}
private MyRunnable runnable = new MyRunnable(this);
Try something like this:
private Runnable myRunnable = new Runnable() {
public void run() {
txtStatus.setText("hello");
}
};
// somewhere in code
txtStatus.postDelayed(myRunnable, 1000);
// in onPause or onDestroy
txtStatus.removeCallbacks(myRunnable);
Notes:
this avoids memory leaks, as your run will never be called after onDestroy if you call removeCallbacks
I replaced new Handler() with txtStatus, because every View has its own instance of Handler and there is no need to create additional one
I want to run a thread (Which does some time consuming task in background and does NOT update UI) it just downloads some files form the internet and it is independent from the UI.
I want to run this thread repeatedly after some time interval.
How can i do this, I have thread something like below:
boolean mResult =false;
void onCreate()
{
DownloadThread mDownloadThread = new DownloadThread();
mDownloadThread.start();
}
class DownloadThread extends Thread implements Runnable
{
public void run()
{
// My download code
mResult = result;
}
}
Do i need to use Handler for implementing this?
Option 1:
volatile boolean flag = true;
public void run()
{
while(flag)
{
// Do your task
try{
Thread.Sleep(interval);
} catch(Exception e){
}
}
}
Option 2:
Timer timer = new Timer();
timer.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
// Do your task
}
}, 0, interval);
Option 3:
volatile boolean flag = true;
public void someMethod(){
// Do your task
try{
Thread.Sleep(interval);
} catch(Exception e){
}
if(flag)
return;
else
someMethod();
}
Option 4:
final Handler handler = new Handler();
volatile boolean flag = true;
Class A implements Runnable{
public void run(){
// Do your Task
}
if(!flag)
handler.postDelayed(a, interval);
}
A a = new A();
handler.postDelayed(a);
There will be many more options. I never tried option 3 and 4. It just came to my mind and I wrote. If I were you I would use any of 1 or 2.
Prefered choice is
java.util.concurrent.ScheduledExecutorService
Newer and robust implementation, More here ScheduledExecutorService
I would use a Timer to achieve this. Try this:
void onCreate()
{
Timer t = new Timer();
t.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
// Download your stuff
}
}, 0, 1000);
}
It starts immediately and the run-Method gets called every second.
I want to setText from within a Thread.
This is my code of the Thread:
private class GenerateThread implements Runnable {
public void run(){
// generate the first music
music = generate(prevmusic, prevmusic.length);
prevmusic = music;
// write the midi
writeMidi(music, song);
textOut.setText("Initialising...");
});
}
}
in my main code, I use
Thread t = new Thread(new GenerateThread());
t.start();
It does not allow me to setText from within the thread.
Following some posts on internet, I have tried using a handler, but that gave me errors, I think I am double defining Runnable this way.
Handler handler (before main)
private class GenerateThread implements Runnable {
public void run(){
handler.post(new Runnable() {
// generate the first music
music = generate(prevmusic, prevmusic.length);
prevmusic = music;
// write the midi
writeMidi(music, song);
textOut.setText("Initialising...");
});
}
}
How can I setText from within the Thread? Thanks!
besides runOnUiThread there is also View#post(Runnable) which I would prefer here because you don't need ugly looking references to the outer Activity (MyActivity.this.runOnUiThread()).
private class GenerateRunnable implements Runnable {
public void run() {
// this code is executed in a background thread.
// generate the first music
music = generate(prevmusic, prevmusic.length);
prevmusic = music;
// write the midi
writeMidi(music, song);
textOut.post(new Runnable() {
public void run() {
// this code is executed on the UI thread.
textOut.setText("Initialising...");
}
});
}
}
#Override
protected void onResume() {
super.onResume();
new Thread(new GenerateRunnable()).start();
}
Also don't confuse Runnable and Thread. A Runnable is just an ordinary class with a run() method. It can be and often is executed on a new Thread. If you want you can also make GenerateThread a real Thread like so:
private class GenerateThread extends Thread {
#Override
public void run() {
// code here.
}
}
// start somewhere
new GenerateThread().start();
And besides using classic Thread you could also think about using AsyncTask since that is made exactly for tasks that do something long running and need to update the UI afterwards or when there is progress.
One can only update the UI from the UI thread. runOnUiThread will allow you to run an action on the UI thread the next time it executes. You can do something like:
runOnUiThread(new Runnable() {
public void run() {
textOut.setText("Initialising...");
}
});
EDIT:
private class GenerateThread implements Runnable {
public void run(){
// generate the first music
music = generate(prevmusic, prevmusic.length);
prevmusic = music;
// write the midi
writeMidi(music, song);
// Update the UI
MyActivity.this.runOnUiThread(new Runnable() {
public void run() {
textOut.setText("Initialising...");
}
});
}
}