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;
}
}
Related
I wrote an application which reads all lines in text files and measure times. I`m wondering what will be the time of whole block.
For example if I start 2 threads at the same time:
for (int i = 0; i < 2; i++) {
t[i] = new Threads(args[j], 2);
j++;
}
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("TIME for block 1 of threads; "
+ (max(new long[]{t[0].getTime(),t[1].getTime()})));
Wait for them to stop processing the files and read operation times (by getTime). Is it good thinking for multithreading that in this case the time of block of threads, will be the maximum time got from thread? I think yes, because other threads will stop working by the time the thread with max time will stop.
Or maybe should I think in another way?
It's dangerous to argue about execution order when having multiple threads! E.g. If you run your code on a single core CPU, the threads will not really run in parallel, but sequentially, so the total run time for both threads is the sum of each thread's run time, not the maximum of both.
Fortunately, there is a very easy way to just measure this if you use an ExecutorService instead of directly using Threads (btw. this is always a good advice):
// 1. init executor
int numberOfThreads = 2; // or any other number
int numberOfTasks = numberOfThreads; // is this true in your case?
ExecutorService executor = Executors.newFixedThreadPool(numberOfThreads);
long startTime = System.currentTimeMillis();
// 2. execute tasks in parallel using executor
for(int i = 0; i < numberOfTasks; i++) {
executor.execute(new Task()); // Task is your implementation of Runnable
}
// 3. initiate shutdown and wait until all tasks are finished
executor.shutdown();
executor.awaitTermination(1, TimeUnit.MINUTES); // we won't wait forever
// 4. measure time
long delta = System.currentTimeMillis() - startTime;
Now, delta holds the total running time of your tasks. You can play around with numberOfThreads to see if more or less threads give different results.
Important note: Reading from a file is not thread-safe in Java, so it is not allowed to share a Reader or InputStream between threads!
As far as my concern You can Use System class's static methods.
You can use it in starting of the block and end of the block and subtract the later one with earlier time.
those are :
System.currentTimeMillis(); // The current value of the system timer, in miliseconds.
or
System.nanoTime(); //The current value of the system timer, in nanoseconds.
You can use
Starting of block
long startTime = System.currentTimeMillis();
End of block
long endTime = System.currentTimeMillis()- startTime;
By this you can calculate.
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.
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().