Java MultiThreading not stopping - java

I have the following code for a kind of 'stopwatch' that extends the Thread class:
package StopWatch;
//Code taken from:
//https://stackoverflow.com/questions/9526041/how-to-program-for-a-stopwatch
public class Stopwatch extends Thread {
private long startTime;
private boolean started;
public void startTimer() {
this.startTime = System.currentTimeMillis();
this.started = true;
this.start();
}
public void run() {
while(started){/*currentTimeMillis increases on its own */}
System.out.println("timer stopped");
}
public int[] getTime() {
long milliTime = System.currentTimeMillis() - this.startTime;
int[] time = new int[]{0,0,0,0};
time[0] = (int)(milliTime / 3600000); //gives number of hours elapsed
time[1] = (int)(milliTime / 60000) % 60; //gives number of remaining minutes elapsed
time[2] = (int)(milliTime / 1000) % 60; //gives number of remaining seconds elapsed
time[3] = (int)(milliTime); //gives number of remaining milliseconds elapsed
return time;
}
public void stopTimer() {
this.started = false;
}
}
and I'm testing it in the following driver class:
import StopWatch.Stopwatch;
public class StopWatchTest {
public static void main(String[] args) {
Stopwatch stopwatch = new Stopwatch();
stopwatch.startTimer();
int sum = 0;
for (long i = 0; i < 100000; i++) {
sum++;
}
int[] time = stopwatch.getTime();
for (int i = 0; i < 4; i++) {
if (i < 3) {
System.out.print(time[i]+":");
} else {
System.out.print(time[i]);
}
}
stopwatch.stopTimer();
}
}
My intent is to use instances of class Stopwatch to measure the performance of various blocks of code (The for-loop in the driver class for instance) by having these Stopwatch objects in a main thread start a timer in separate thread before executing the blocks of code I want to evaluate, then have them (the Stopwatch objects) stop their timer once execution of said blocks in the main thread have finished. I understand that there are much simpler and easier ways to do this but I wanted to try doing it this way as sort of a "proof of concept" and to simply get better with multi-threading, but I'm encountering some problems:
1) When I run the driver class StopWatchTest I get seemingly random and arbitrary output each time (but mostly 0:0:0:0)
2) The main thread (or possibly the Stopwatch thread, I'm not even sure anymore) seems to never stop executing after I get outputs like 0:0:0:0
3) When I try debugging with breakpoints and the like I get completely unexpected behavior depending on where I put the breakpoints (The main thread does sometime finish execution but with random outputs like 0:0:13:2112 and other times I just get stuck in the Stopwatch thread)
Point 3 doesn't concern me as much as 1 and 2 as I have limited knowledge of how multi-threading behaves when one or several of the threads are paused at breakpoints for debugging (I suspect that when I break in the main thread the Stopwatch thread continues running). Points 1 and 2 bother me much more as I cannot see why they would be occurring.

To get you started, you should flag the boolean started as volatile:
private volatile boolean started;
That should work, but it would make a busy loop, which is very bad for your CPU usage.
You should look to wait()/notify() methods next.

Related

Threads in Java - Sum of N numbers

I tried to perform sum of N numbers using conventional method and also using threads to see the performance of threads. I see that the conventional method runs faster than the thread based.
My plan is to break down the upper limit(N) into ranges then run a thread for each range and finally add the sum calculated from each thread.
stats in milliseconds :
248
500000000500000000
-----same with threads------
498
500000000500000000
Here I see the approach using threads took ~500 milliseconds and conventional method took only ~250 seconds.
I wanted to know If I am correctly implementing threads for this problem.
Thanks
code :
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class MyThread implements Runnable {
private int from , to , sum;
public MyThread(long from , long to) {
this.from = from;
this.to = to;
sum = 0;
}
public void run() {
for(long i=from;i<=to;i++) {
sum+=i;
}
}
public long getSum() {
return this.sum;
}
}
public class exercise {
public static void main(String args[]) {
long startTime = System.currentTimeMillis();
long sum = 0;
for(long i=1;i<=1000000000;i++) {
sum+=i;
}
long endTime = System.currentTimeMillis();
long duration = (endTime - startTime); //Total execution time in milli seconds
System.out.println(duration);
System.out.println(sum);
System.out.println("-----same with threads------");
ExecutorService executor = Executors.newFixedThreadPool(5);
MyThread one = new MyThread(1, 100000);
MyThread two = new MyThread(100001, 10000000);
MyThread three = new MyThread(10000001, 1000000000);
startTime = System.currentTimeMillis();
executor.execute(one);
executor.execute(two);
executor.execute(three);
executor.shutdown();
// Wait until all threads are finish
while (!executor.isTerminated()) {
}
endTime = System.currentTimeMillis();
System.out.println(endTime - startTime);
long thsum = one.getSum() + two.getSum() + three.getSum();
System.out.println(thsum);
}
}
It only makes sense to split the work into multiple threads when each thread is assigned the same amount of work.
In your case, the first thread does almost nothing, the second thread does almost 1% of the work, and the third thread does 99% of the work.
Therefore, you pay the overhead for running multiple threads without benefiting from the parallel execution.
Splitting the work evenly, as follows, should yield better results:
MyThread one = new MyThread(1, 333333333);
MyThread two = new MyThread(333333334, 666666667);
MyThread three = new MyThread(666666668, 1000000000);
The multithread part of your example includes the time for thread creation. Thread creation is an expensive operation and I presume that it is responsible for a large share of the difference between the single thread and multithread approaches.
Your question was if you are correctly implementing the threads. Did you mean implementing the runnable tasks? If so, I wonder why you have distributed the number ranges so unevenly. The task three seems to be far bigger than the others and as a result the performance will be close to a single thread version however you choose to set up the threads.

Java factorial calculation with thread pool

I achieved to calculate factorial with two threads without the pool. I have two factorial classes which are named Factorial1, Factorial2 and extends Thread class. Let's consider I want to calculate the value of !160000. In Factorial1's run() method I do the multiplication in a for loop from i=2 to i=80000 and in Factorial2's from i=80001 to 160000. After that, i return both values and multiply them in the main method. When I compare the execution time it's much better (which is 5000 milliseconds) than the non-thread calculation's time (15000 milliseconds) even with two threads.
Now I want to write clean and better code because I saw the efficiency of threads at factorial calculation but when I use a thread pool to calculate the factorial value, the parallel calculation always takes more time than the non-thread calculation (nearly 16000). My code pieces look like:
for(int i=2; i<= Calculate; i++)
{
myPool.execute(new Multiplication(result, i));
}
run() method which is in Multiplication class:
public void run()
{
s1.Mltply(s2); // s1 and s2 are instances of my Number class
// their fields holds BigInteger values
}
Mltply() method which is in Number class:
public void Multiply(int number)
{
area.lock(); // result is going wrong without lock
Number temp = new Number(number);
value = value.multiply(temp.value); // value is a BigInteger
area.unlock();
}
In my opinion this lock may kills the all advantage of the thread usage because it seems like all that threads do is multiplication but nothing else. But without it, i can't even calculate the true result. Let's say i want to calculate !10, so thread1 calculates the 10*9*8*7*6 and thread2 calculate the 5*4*3*2*1. Is that the way I'm looking for? Is it even possible with thread pool? Of course execution time must be less than the normal calculation...
I appreciate all your help and suggestion.
EDIT: - My own solution to the problem -
public class MyMultiplication implements Runnable
{
public static BigInteger subResult1;
public static BigInteger subResult2;
int thread1StopsAt;
int thread2StopsAt;
long threadId;
static boolean idIsSet=false;
public MyMultiplication(BigInteger n1, int n2) // First Thread
{
MyMultiplication.subResult1 = n1;
this.thread1StopsAt = n2/2;
thread2StopsAt = n2;
}
public MyMultiplication(int n2,BigInteger n1) // Second Thread
{
MyMultiplication.subResult2 = n1;
this.thread2StopsAt = n2;
thread1StopsAt = n2/2;
}
#Override
public void run()
{
if(idIsSet==false)
{
threadId = Thread.currentThread().getId();
idIsSet=true;
}
if(Thread.currentThread().getId() == threadId)
{
for(int i=2; i<=thread1StopsAt; i++)
{
subResult1 = subResult1.multiply(BigInteger.valueOf(i));
}
}
else
{
for(int i=thread1StopsAt+1; i<= thread2StopsAt; i++)
{
subResult2 = subResult2.multiply(BigInteger.valueOf(i));
}
}
}
}
public class JavaApplication3
{
public static void main(String[] args) throws InterruptedException
{
int calculate=160000;
long start = System.nanoTime();
BigInteger num = BigInteger.valueOf(1);
for (int i = 2; i <= calculate; i++)
{
num = num.multiply(BigInteger.valueOf(i));
}
long end = System.nanoTime();
double time = (end-start)/1000000.0;
System.out.println("Without threads: \t" +
String.format("%.2f",time) + " miliseconds");
System.out.println("without threads Result: " + num);
BigInteger num1 = BigInteger.valueOf(1);
BigInteger num2 = BigInteger.valueOf(1);
ExecutorService myPool = Executors.newFixedThreadPool(2);
start = System.nanoTime();
myPool.execute(new MyMultiplication(num1,calculate));
Thread.sleep(100);
myPool.execute(new MyMultiplication(calculate,num2));
myPool.shutdown();
while(!myPool.isTerminated()) {} // waiting threads to end
end = System.nanoTime();
time = (end-start)/1000000.0;
System.out.println("With threads: \t" +String.format("%.2f",time)
+ " miliseconds");
BigInteger result =
MyMultiplication.subResult1.
multiply(MyMultiplication.subResult2);
System.out.println("With threads Result: " + result);
System.out.println(MyMultiplication.subResult1);
System.out.println(MyMultiplication.subResult2);
}
}
input : !160000
Execution time without threads : 15000 milliseconds
Execution time with 2 threads : 4500 milliseconds
Thanks for ideas and suggestions.
You may calculate !160000 concurrently without using a lock by splitting 160000 into disjunct junks as you explaint by splitting it into 2..80000 and 80001..160000.
But you may achieve this by using the Java Stream API:
IntStream.rangeClosed(1, 160000).parallel()
.mapToObj(val -> BigInteger.valueOf(val))
.reduce(BigInteger.ONE, BigInteger::multiply);
It does exactly what you try to do. It splits the whole range into junks, establishes a thread pool and computes the partial results. Afterwards it joins the partial results into a single result.
So why do you bother doing it by yourself? Just practicing clean coding?
On my real 4 core machine computation in a for loop took 8 times longer than using a parallel stream.
Threads have to run independent to run fast. Many dependencies like locks, synchronized parts of your code or some system calls leads to sleeping threads which are waiting to access some resources.
In your case you should minimize the time a thread is inside the lock. Maybe I am wrong, but it seems like you create a thread for each number. So for 1.000! you spawn 1.000 Threads. All of them trying to get the lock on area and are not able to calculate anything, because one thread has become the lock and all other threads have to wait until the lock is unlocked again. So the threads are only running in serial which is as fast as your non-threaded example plus the extra time for locking and unlocking, thread management and so on. Oh, and because of cpu's context switching it gets even worse.
Your first attempt to splitt the factorial in two threads is the better one. Each thread can calculate its own result and only when they are done the threads have to communicate with each other. So they are independent most of the time.
Now you have to generalize this solution. To reduce context switching of the cpu you only want as many threads as your cpu has cores (maybe a little bit less because of your OS). Every thread gets a rang of numbers and calculates their product. After this it locks the overall result and adds its own result to it.
This should improve the performance of your problem.
Update: You ask for additional advice:
You said you have two classes Factorial1 and Factorial2. Probably they have their ranges hard codes. You only need one class which takes the range as constructor arguments. This class implements Runnable so it has a run-Method which multiplies all values in that range.
In you main-method you can do something like that:
int n = 160_000;
int threads = 2;
ExecutorService executor = Executors.newFixedThreadPool(threads);
for (int i = 0; i < threads; i++) {
int start = i * (n/threads) + 1;
int end = (i + 1) * (n/threads) + 1;
executor.execute(new Factorial(start, end));
}
executor.shutdown();
executor.awaitTermination(1, TimeUnit.DAYS);
Now you have calculated the result of each thread but not the overall result. This can be solved by a BigInteger which is visible to the Factorial-class (like a static BigInteger reuslt; in the same main class.) and a lock, too. In the run-method of Factorial you can calculate the overall result by locking the lock and calculation the result:
Main.lock.lock();
Main.result = Main.result.multiply(value);
Main.lock.unlock();
Some additional advice for the future: This isn't really clean because Factorial needs to have information about your main class, so it has a dependency to it. But ExecutorService returns a Future<T>-Object which can be used to receive the result of the thread. Using this Future-Object you don't need to use locks. But this needs some extra work, so just try to get this running for now ;-)
In addition to my Java Stream API solution here another solution which uses a self-managed thread-pool as you demanded:
public static final int CHUNK_SIZE = 10000;
public static BigInteger fac(int max) {
ExecutorService executor = newCachedThreadPool();
try {
return rangeClosed(0, (max - 1) / CHUNK_SIZE)
.mapToObj(val -> executor.submit(() -> prod(leftBound(val), rightBound(val, max))))
.map(future -> valueOf(future))
.reduce(BigInteger.ONE, BigInteger::multiply);
} finally {
executor.shutdown();
}
}
private static int leftBound(int chunkNo) {
return chunkNo * CHUNK_SIZE + 1;
}
private static int rightBound(int chunkNo, int max) {
return Math.min((chunkNo + 1) * CHUNK_SIZE, max);
}
private static BigInteger valueOf(Future<BigInteger> future) {
try {
return future.get();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
private static BigInteger prod(int min, int max) {
BigInteger res = BigInteger.valueOf(min);
for (int val = min + 1; val <= max; val++) {
res = res.multiply(BigInteger.valueOf(val));
}
return res;
}

How to run a Thread for a user specified amount of time?

Am creating a program that is based on mixing and making perturbation in a population containing solutions Vector.
So I created a for loop that stops after a certain time given by the user.
Inside the loop, am going to call 5 procedures and I thought that if i put each procedure in a thread will make the program making more solutions in a same time than calling normal methods.
Here 5 created the 5 threads, but when i start them the don't want to stop even if i use the Thread.stop, Thread.suspend, Thread.interrupt or Thread.destroy
Here is my code and could u help me with your ideas ?
I have inserted a new variable :
public volatile boolean CrossOpb = true;`
Here is my code:
Thread CrossOp = new Thread(new Runnable() {
public void run() {
while(CrossOpb == true){
int rdmCross2=(int) (Math.random() * allPopulation.size()) ; // Crossover 1st vector
int rdmCross1=(int) (Math.random() * allPopulation.size()) ;
Vector muted = new Vector();
Vector copy = copi((Vector) allPopulation.get(rdmCross2));
Vector callp = copi((Vector) allPopulation.get(rdmCross1));
muted = crossover(callp, copy);
System.out.println("cross over Between two Randoms ----------->");
affiche_resultat(muted);
allPopulation.add(muted);
}
}
});
The loop :
CrossOp.setDaemon(true);
int loop = 1;
long StartTime = System.currentTimeMillis() / 1000;
for (int i = 0; i < loop; ++i) {
loop++;
if (timevalue < ((System.currentTimeMillis() / 1000) - StartTime)) {
loop = 0;
CrossOpb = false;
}
CrossOp.start();
}
I already answered to a similar question. In that case, it was C#, but the concept is the same.
You must not kill threads. Threads must exit on their own will.
Just put a volatile boolean variable somewhere, and set it to true/false, when you want your thread to terminate, then, in the thread, replace the while (true) with a while (myVariable == true/false).
Anyway, you say:
Inside the loop, am going to call 5 procedures ant i thought that if i put each procedure in a thread will make the program making more solutions in a same time than calling normal methods.
Well, that's generally false. If the procedures are data-dependent (each of them depends on the results of the previous one), putting them on threads will change nothing. It might be smarter to put iterations in a pipeline, so that you have 5 threads executing steps of successive iterations. I'm not sure if that's possible for genetic algorithms, and anyway you'll have to handle some special case (e.g. a mutation, that alters the population of partially computed iterations).
How to run a Thread for a specific amount of time:
Here is the basic approach is to keep calculate how long the Thread has run and exit and return the result, which in our case here is details on how long the Thread executed.
NOTE: you must use System.nanoTime() as System.currentTimeMillis() will just return the same thing every time you call it in the method.
I use a Random number to calculate different lifetimes for each of the Callables so that you can see that they don't execute exactly for the time specified but they are very very close, and the variance of the delta is pretty consistent, at least on my machine.
Here a Gist of the code below for easier access.
package com.stackoverflow.Q18818482;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Random;
import java.util.concurrent.*;
public class Question18818482
{
public static Random RND;
static
{
RND = new Random();
}
public static void main(final String[] args)
{
try
{
final ExecutorService es = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
final List<Future<String>> results = new ArrayList<>(10);
for (int i = 0; i < 10; i++)
{
results.add(es.submit(new TimeSliceTask(RND.nextInt(10), TimeUnit.SECONDS)));
}
es.shutdown();
while(!results.isEmpty())
{
final Iterator<Future<String>> i = results.iterator();
while (i.hasNext())
{
final Future<String> f = i.next();
if (f.isDone())
{
System.out.println(f.get());
i.remove();
}
}
}
}
catch (InterruptedException e)
{
throw new RuntimeException(e);
}
catch (ExecutionException e)
{
throw new RuntimeException(e);
}
}
public static class TimeSliceTask implements Callable<String>
{
private final long timeToLive;
private final long duration;
public TimeSliceTask(final long timeToLive, final TimeUnit timeUnit)
{
this.timeToLive = System.nanoTime() + timeUnit.toNanos(timeToLive);
this.duration = timeUnit.toMillis(timeToLive);
}
#Override
public String call() throws Exception
{
while( timeToLive <= System.nanoTime() )
{
// simulate work here
Thread.sleep(500);
}
final long end = System.nanoTime();
return String.format("Finished Elapsed Time = %d, scheduled for %d", TimeUnit.NANOSECONDS.toMillis(timeToLive - end), this.duration );
}
}
}
Here is what one runs output looks like
NOTE: All times are in milliseconds
Finished Elapsed Time = 999, scheduled for 1000
Finished Elapsed Time = 2998, scheduled for 3000
Finished Elapsed Time = 5999, scheduled for 6000
Finished Elapsed Time = 1994, scheduled for 2000
Finished Elapsed Time = 8994, scheduled for 9000
Finished Elapsed Time = 6993, scheduled for 7000
Finished Elapsed Time = 6993, scheduled for 7000
Finished Elapsed Time = 5993, scheduled for 6000
Finished Elapsed Time = 5998, scheduled for 6000
After reading the whole last night about threads, i have discovered that the solution for my problem was not that hard.
The idea was to edit the condition of the stopping loop inside the thread so we control it by giving it a specific amount of time to run for it and here is my Example :
class ProcessorCordm extends Thread {
int runningtime;
public ProcessorCordm(int runningtime) {
this.runningtime = runningtime;
}
public void run() {
int loop = 1;
long StartTime = System.currentTimeMillis() / 1000;
for (int i = 0; i < loop; ++i) {
int rdmCross2 = (int) (Math.random() * allPopulation.size()); // Crossover 1st vector
int rdmCross1 = (int) (Math.random() * allPopulation.size());
Vector muted = new Vector();
Vector copy = copi((Vector) allPopulation.get(rdmCross2));
Vector callp = copi((Vector) allPopulation.get(rdmCross1));
muted = crossover(callp, copy);
System.out.println("cross over Between two Randoms ----------->");
affiche_resultat(muted);
addsolution(muted);
loop++;
if (timevalue < ((System.currentTimeMillis() / 1000) - StartTime)) {
loop = 0;
}
}
}
}
So if i want to run my Thread for 10 seconds i only need to :
ProcessorCoG CrossOpg = new ProcessorCoG(10);
And fo my case, I have to call many Threads simultaneously working for a specific TimeValue so i used the ExecutorServiceClass :
ProcessorCoG CrossOpg = new ProcessorCoG(timevalue);//extends Thread class
ProcessorCordm CrossOp = new ProcessorCordm(timevalue);//extends Thread class
ProcessorCordm CrossOp2 = new ProcessorCordm(timevalue);//extends Thread class
MutateGb MutGb = new MutateGb(timevalue);//extends Thread class
MutateRdm MutRdm = new MutateRdm(timevalue);//extends Thread class
MbsRdm MbsR = new MbsRdm(timevalue);//extends Thread class
ExecutorService executor = Executors.newFixedThreadPool(6);
executor.submit(MutGb);
executor.submit(MutRdm);
executor.submit(CrossOp);
executor.submit(CrossOp2);
executor.submit(CrossOpg);
executor.submit(MbsR);

(Java) Ticker that adds to counter variable

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.

read array in certain time range

How can I read an array in java in a certain time? Lets say in 1000 milliseconds.
for example:
float e[]=new float [512];
float step = 1000.0 / e.length; // I guess we need something like that?
for(int i=0; i<e.length; i++){
}
You'd need a Timer. Take a look at its methods... There's a number of them, but they can be divided into two categories: those that schedule at a fixed delay (the schedule(... methods) and those that schedule at a fixed rate (the scheduleAtFixedRate(... methods).
A fixed delay is what you want if you require "smoothness". That means, the time in between executions of the task is mostly constant. This would be the sort of thing you'd require for an animation in a game, where it's okay if one execution might lag behind a bit as long as the average delay is around your target time.
A fixed rate is what you want if you require the task's executions to amount to a total time. In other words, the average time over all executions must be constant. If some executions are delayed, multiple ones can then be run afterwards to "catch up". This is different from fixed delay where a task won't be run sooner just because one might have "missed" its cue.
I'd reckon fixed rate is what you're after. So you'd need to create a new Timer first. Then you'd need to call method scheduleAtFixedRate(TimerTask task, long delay, long period). That second argument can be 0 if you wish the timer to start immediately. The third argument should be the time in between task runs. In your case, if you want the total time to be 1000 milliseconds, it'd be 1000/array size. Not array size/1000 as you did.
That leaves us with the first argument: a TimerTask. Notice that this is an abstract class, which requires only the run() method to be implemented. So you'll need to make a subclass and implement that method. Since you're operating over an array, you'll need to supply that array to your implementation, via a constructor. You could then keep an index of which element was last processed and increment that each time run() is called. Basically, you're replacing the for loop by a run() method with a counter. Obviously, you should no longer do anything if the counter has reached the last element. In that case, you can set some (boolean) flag in your TimerTask implementation that indicates the last element was processed.
After creating your TimerTask and scheduling it on a Timer, you'll need to wait for the TimerTask's flag to be set, indicating it has done its work. Then you can call cancel() on the Timer to stop it. Otherwise it's gonna keep calling useless run() methods on the task.
Do keep the following in mind: if the work done in the run() method typically takes longer than the interval between two executions, which in your case would be around 2 milliseconds, this isn't gonna work very well. It only makes sense to do this if the for loop would normally take less than 1 second to complete. Preferably much less.
EDIT: oh, also won't work well if the array size gets too close to the time limit. If you want 1000 milliseconds and you have 2000 array elements, you'll end up passing in 0 for the period argument due to rounding. In that case you might as well run the for loop.
EDIT 2: ah why not...
import java.util.Random;
import java.util.Timer;
public class LoopTest {
private final static long desiredTime = 1000;
public static void main(String[] args) {
final float[] input = new float[512];
final Random rand = new Random();
for(int i = 0; i < input.length; ++i) {
input[i] = rand.nextFloat();
}
final Timer timer = new Timer();
final LoopTask task = new LoopTask(input);
double interval = ((double)desiredTime/((double)input.length));
long period = (long)Math.ceil(interval);
final long t1 = System.currentTimeMillis();
timer.scheduleAtFixedRate(task, 0, period);
while(!task.isDone()) {
try {
Thread.sleep(50);
} catch(final InterruptedException i) {
//Meh
}
}
final long t2 = System.currentTimeMillis();
timer.cancel();
System.out.println("Ended up taking " + (t2 - t1) + " ms");
}
}
import java.util.TimerTask;
public class LoopTask extends TimerTask {
private final float[] input;
private int index = 0;
private boolean done = false;
public LoopTask(final float[] input) {
this.input = input;
}
#Override
public void run() {
if(index == input.length) {
done = true;
} else {
//TODO: actual processing goes here
System.out.println("Element " + index + ": " + input[index]);
++index;
}
}
public boolean isDone() {
return done;
}
}
Change your step to be time per number (or total time divided by number of steps)
float step = 1000.0 / e.length;
Inside your for() loop:
try{
Thread.sleep(step);
}catch(InterruptedException e){
e.printStackTrace();
}

Categories