I'm working with a RF reader device which has C# API.Based on its API, you'll need to manually invoke its read function to read/badge a card.
So my workaround is to use Timer to execute reading every 'n' seconds.
My problem is that Timer continuously executing, regardless of Thread.sleep() was invoke inside it's action.
Timer timer = new Timer(TimerCallback, null, 500, 1000); // From main() method
// The action that Timer executes
private void TimerCallback(Object o)
{
scan(); // Action for reading/badging card
scand.WaitOne(); // AutoResetEvent(true)
GC.Collect(); // Force garbage collection
}
Thread.sleep() invoke inside the scan().
In Java, I use synchronized() to wait the other thread to call invoke(). I've searched for the whole day and I can't see a workaround that will be equivalent to ScheduledExecutorService and synchronized().
I hope there is a workaround with this cause I need it as soon as possible.
Thanks!
The most reliable way I could find was by re-starting the timer in the callback. This way the callback is not interrupted when active.
Timer timer = new Timer(TimerCallback, null, 500, 0);
private void TimerCallback(Object o)
{
scan();
scand.WaitOne();
timer.Change(500, 0);
}
The timer.Change re-schedules the timer.
Note: I removed the repetition in the Timer start up.
BTW: I removed the GC.Collect() as I consider that bad practice and useless in most cases.
Additionally you could get the time at the start of the method (Use Stopwatch) and calculate the required time delta to be passed to timer.Change :
Timer timer = new Timer(TimerCallback, null, 500, 0);
Stopwatch stopwatch = Stopwatch.StartNew();
private void TimerCallback(Object o)
{
var entered = stopwatch.ElapsedMilliseconds;
scan();
scand.WaitOne();
var duration = stopwatch.ElapsedMilliseconds - entered;
var delay = Math.Max(0, 500 - duration);
timer.Change(delay, 0);
}
This way the callback will be invoked after 500 ms minus the time it took to execute the scan functions. Set up like this and you might remove the Sleep from the Scan.
The reason for the double callback in your code is probably that the timer executes the callback on another thread when the first thread is still executing the callback.
Another solution might be to not use a Timer at all. Just loop and use a Stopwatch to calculate a time period to Sleep:
private void Scan()
{
while(scanning)
{
var entered = stopwatch.ElapsedMilliseconds;
scan();
scand.WaitOne();
var duration = stopwatch.ElapsedMilliseconds - entered;
var delay = Math.Max(0, 500 - duration);
Thread.Sleep(delay);
}
}
Make sure you call this method on a separate thread (you could use a Task)
Related
In my Android app, I have a snippet of code, similar to Run code for x seconds in Java?
long t= System.currentTimeMillis();
long end = t+15000;
while(System.currentTimeMillis() < end) {
//useful calculation
}
And this code will freeze the UI thread, so I'm wondering if there's a way to continuously pass in data to my AsyncTask that will do the calculation in the background thread to avoid freezing? Or is there a better way, or to keep calling AsyncTask from within my while loop?
For this purpose, use a Handler instead.
It goes like this :
Handler timerHandler = new Handler();
Runnable timerRunnable = new Runnable() {
#Override
public void run() {
//READ HERE WHAT YOU NEED FROM THE SENSOR (useful calculation)
//And then set the next execution of the sensor reading
timerHandler.postDelayed(this, 1000); //runs 1000 milliseconds
}
};
//Launch It for the first time
timerHandler.post(timerRunnable);
//Whenever you would like to stop it, use the following commented line
//timerHandler.removeCallbacks(timerRunnable);
Im trying to get a timer to work in my current java project that adds 1 to an integer variable every n microseconds (e.g. 500 for 1/2 a second), within an infinite loop, so that it is always running while the program runs.
Heres the code i have currently:
public class Ticker
{
public int time = 0;
long t0, t1;
public void tick(int[] args)
{
for (int i = 2; i < 1; i++)
{
t0 = System.currentTimeMillis();
do
{
t1 = System.currentTimeMillis();
}
while (t1 - t0 < 500);
time = time + 1;
}
}
}
Everyone was so helpful with my last question, hopefully this one is just as easy
Here is an comparable ScheduledExecutorService example which will update the time variable with a 500 millisecond interval:
ScheduledExecutorService exec = Executors.newScheduledThreadPool(1);
exec.scheduleAtFixedRate(new Runnable(){
private int time = 0;
#Override
public void run(){
time++;
System.out.println("Time: " + time);
}
}, 0, 500, TimeUnit.MILLISECONDS);
This approach is preferred over using Timer.
I think you want
Thread.sleep(500);
At the moment you're consuming CPU cycles waiting for 500ms (you mention microseconds but I believe you want milliseconds). The above puts your current thread to sleep for 500ms and your process won't consume any CPU (or minimal at least - garbage collection will still be running). If you watch the CPU when you run your version you should see the difference.
See here for more info.
If you need to do it in a different thread, take a look on Timer:
int delay = 500; //milliseconds
ActionListener taskPerformer = new ActionListener() {
public void actionPerformed(ActionEvent evt) {
time++
}
};
new Timer(delay, taskPerformer).start();
Note that the code above cannot utilize a local variable (they must be declared as final to access them in an anonymous class). It can be a member however.
What you have is rather inefficient, since it wastes CPU cycles waiting for the next wakeup time. If I were you, I'd rewrite the function using Thread.sleep().
As to why your current code doesn't work, your for loop conditions are off, so the loop is never entered.
To have the timer code run concurrently with whatever other logic you have in your program, you'll need to look into threading.
It sounds like you might want to look into multithreading. If you search SO for this, you will find several good question/answer threads. There are also tutorials elsewhere on the web...
Have a look at Timer or better ScheduledExecutorService. They enable you to execute some action periodically and handle the computations surrounding that.
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().
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().
I need to run some code for a predefined length of time, when the time is up it needs to stop. Currently I am using a TimerTask to allow the code to execute for a set amount of time but this is causing endless threads to be created by the code and is just simply not efficient. Is there a better alternative?
Current code;
// Calculate the new lines to draw
Timer timer3 = new Timer();
timer3.schedule(new TimerTask(){
public void run(){
ArrayList<String> Coords = new ArrayList<String>();
int x = Float.valueOf(lastFour[0]).intValue();
int y = Float.valueOf(lastFour[1]).intValue();
int x1 = Float.valueOf(lastFour[2]).intValue();
int y1 = Float.valueOf(lastFour[3]).intValue();
//Could be the wrong way round (x1,y1,x,y)?
Coords = CoordFiller.coordFillCalc(x, y, x1, y1);
String newCoOrds = "";
for (int j = 0; j < Coords.size(); j++)
{
newCoOrds += Coords.get(j) + " ";
}
newCoOrds.trim();
ClientStorage.storeAmmendedMotion(newCoOrds);
}
}
,time);
If you are using Java5 or later, consider ScheduledThreadPoolExecutor and Future. With the former, you can schedule tasks to be run after a specified delay, or at specified intervals, thus it takes over the role of Timer, just more reliably.
The Timer facility manages the execution of deferred ("run this task in 100 ms") and periodic ("run this task every 10 ms") tasks. However, Timer has some drawbacks, and ScheduledThreadPoolExecutor should be thought of as its replacement. [...]
A Timer creates only a single thread for executing timer tasks. If a timer task takes too long to run, the timing accuracy of other TimerTasks can suffer. If a recurring TimerTask is scheduled to run every 10 ms and another TimerTask takes 40 ms to run, the recurring task either (depending on whether it was scheduled at fixed rate or fixed delay) gets called four times in rapid succession after the long-running task completes, or "misses" four invocations completely. Scheduled thread pools address this limitation by letting you provide multiple threads for executing deferred and periodic tasks.
Another problem with Timer is that it behaves poorly if a TimerTask throws an unchecked exception. The Timer thread doesn't catch the exception, so an unchecked exception thrown from a TimerTask terminates the timer thread. Timer also doesn't resurrect the thread in this situation; instead, it erroneously assumes the entire Timer was cancelled. In this case, TimerTasks that are already scheduled but not yet executed are never run, and new tasks cannot be scheduled.
From Java Concurrency in Practice, section 6.2.5.
And Futures can be constrained to run at most for the specified time (throwing a TimeoutException if it could not finish in time).
Update
If you don't like the above, you can make the task measure its own execution time, as below:
int totalTime = 50000; // in nanoseconds
long startTime = System.getNanoTime();
boolean toFinish = false;
while (!toFinish)
{
System.out.println("Task!");
...
toFinish = (System.getNanoTime() - startTime >= totalTime);
}
[...] Currently I am using a TimerTask to allow the code to execute for a set amount of time [...]
The timer task will never stop the currently running task. In fact, it's only purpose is to restart the task over and over again.
There is no easy way of solving this without tight cooperation with the executing task. The best way is to let the task monitor it's own execution, and make sure that it returns (terminates) when its time is up.
If by stopping you mean the program has to exit, the solution is to create a thread for your processing and mark it as daemon, start it and in the main thread sleep for the time required, then simply return from the main() method.
Scratch that if by stopping, you mean just to stop the processing.
It should also be noted that generally you only need to create one Timer(). From the code snippet I would guess you are creating multiple Timer() objects.
The time in the schedule method is the time to run at, not how long to run for.
Consider putting a start time before the for loop & putting a break in the for loop if you have exceeded the time limit.
long startedAt = System.currentTimeMillis();
long finishedCorrectly = true;
for (int j = 0; j < Coords.size(); j++) {
newCoOrds += Coords.get(j) + " ";
if ((System.currentTimeMillis() - startedAt) > MAX_TIME_TO_RUN) {
finishedCorrectly = false;
break;
}
}