I got an issue with a multi-threaded program.
I need to simulate a lot of people trying to book the same flight at the same time, using no locks.
So I made an ExecutorService and used that to pool threads so I can have many simultaneous attempt going at once.
The problem is though, the program sort of reaches the end and right before it prints out all the results, it just sits there and runs forever. I've tried to go into all the other classes that utilize a connection to a database and simply close them off manually. No luck.
package dbassignment4;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
*
* #author Vipar
*/
public class Master{
private static final int POOL_SIZE = 50;
public static boolean planeIsBooked = false;
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
int success = 0;
int seatNotReserved = 0;
int seatNotReservedByCustomerID = 0;
int reservationTimeout = 0;
int seatIsOccupied = 0;
int misc = 0;
HelperClass.clearAllBookings("CR9");
Thread t = new Thread(new DBMonitor("CR9"));
long start = System.nanoTime();
//HelperClass.clearAllBookings("CR9");
ExecutorService pool = new ThreadPoolExecutor(
POOL_SIZE, POOL_SIZE,
0L,
TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>(POOL_SIZE));
int threadsStarted = 0;
List<Future<Integer>> results = new ArrayList<>();
long id = 1;
t.start();
while(planeIsBooked == false) {
try {
Future<Integer> submit = pool.submit(new UserThread(id));
results.add(submit);
} catch (RejectedExecutionException ex) {
misc++;
continue;
}
threadsStarted++;
id++;
}
pool.shutdownNow();
int count = 0;
for(Future<Integer> i : results) {
try {
switch(i.get()) {
case 0:
// Success
success++;
break;
case -1:
// Seat is not Reserved
seatNotReserved++;
break;
case -2:
// Seat is not Reserved by Customer ID
seatNotReservedByCustomerID++;
break;
case -3:
// Reservation Timeout
reservationTimeout++;
break;
case -4:
// Seat is occupied
seatIsOccupied++;
break;
default:
misc++;
// Everything else fails
break;
}
} catch (ExecutionException | InterruptedException ex) {
misc++;
}
count++;
System.out.println("Processed Future Objects: " + count);
// HERE IS WHERE IT LOOPS
}
Here is the rest of the code it doesn't execute right after:
long end = System.nanoTime();
long time = end - start;
System.out.println("Threads Started: " + threadsStarted);
System.out.println("Successful Bookings: " + success);
System.out.println("Seat Not Reserved when trying to book: " + seatNotReserved);
System.out.println("Reservations that Timed out: " + reservationTimeout);
System.out.println("Reserved by another ID when trying to book: " + seatNotReservedByCustomerID);
System.out.println("Bookings that were occupied: " + seatIsOccupied);
System.out.println("Misc Errors: " + misc);
System.out.println("Execution Time (Seconds): " + (double) (time / 1000000000));
}
}
Can you spot the issue? I put in a comment where the code stops running.
When planeIsBooked become true, looks like your planeIsBooked will never be initialize to true in the while loop. So make sure your loop is not infinite.
first thing is while(planeIsBooked == false) evaluates to true always because
planeIsBooked = false always , nowhere its initialized to true.
so how come your while loop condition becomes false and come out?
set inside while loop somewhere planeIsBooked = true to come out of while loop.
Couple of Things :
First , After you call pool.shutdownNow(); - you are proceeding to try fetching the results straight away. The call shutDownNow() is not blocking and is not a definite indication that pool is stopped. For that - you should call pool.awaitTermination().
Second, It is not clear what you mean by your comment -
// HERE IS WHERE IT LOOPS
This is under a loop - and looking at the loop - if there is an exception thrown in the switch case - then it will go into the catch - ignore it and loop. Did you check for exceptions ?
Go through this answer for why you should declare static variables as volatile in multi thread environment.
Even though , your static variable is volatile , the following lines is dangerous
while(planeIsBooked == false) {
Future<Integer> submit = pool.submit(new UserThread(id));
}
Consider your booking flight taking avg 2 secs . And you have about 300 seats ( assumption). Your planeIsBooked field would become true after 600 seconds ( if its running in single thread). With 50 size pool it would run in 12 seconds.
With the above assumption , your loop would run 12 seconds.
Now , think about how many time the submit request statement executed ? i times.
Even though you have just 300 seats , you might given appox more minimum million requests with in 12 seconds.
Thus, think about the number Jobs in queue before calling Shutdown now() . THis is not the right way of terminating loop
If you know the max size of your flight seat , why dont you use it in for loop ( may be externalize the parameter in for loop , instead of variable to hold
Related
I have an enterprise application running on a server that accepts files. Tens of thousands of files are submitted every day by users. The customer wants exactly 50 of these files to be automatically selected for audit each day.
The requirements are:
the files must be selected as they come in (we can't wait for all the files to come in and then choose 50 at the end of the day)
the files selected must meet some other criteria, which they haven't told me yet, but I am assured there will still be thousands of files that meet these criteria
the system must not be "game-able". That is - they don't want users who submit files to realise that if they wait until the afternoon or something, their files never get audited. This means we can't just choose the first 50 that come in, the selected files must be randomly spread out throughout the day.
we have to have EXACTLY 50 files. Or so they say. But I'm pretty sure if it just so happened that no user submitted a file that matched the criteria after midday one day, and we only got 25 files, they'd be ok with that. So I can assume that the types of files I'm interested in are submitted with a reasonably regular frequency throughout the day.
I figure then, that I need some function that calculates a probability that a file will be selected, that uses the number of currently chosen files and the time of day as inputs.
I've created a test harness. Please forgive the dodgy code. In this, the "pushTask" thread simulates files coming in by adding them to a stack. "Files" in this test are just Strings with a random number on the end.
The "pullTask" thread simulates files being pulled off the stack. It asks requirementsFunction() if the "file" meets the extra requirements needed (and in this test that's just - does it end in a zero), and it asks probabilityFunction() if it should select the file. If a file is selected, it is printed to System.out.
Really I need some help as to what to put in probabilityFunction(), because at the moment what's in there is garbage (I've left it in so you can see what I've tried). Or if someone knows of a mathematical probability function that uses items/time that would be great too.
package com.playground;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Random;
public class ProbabilisticSelection {
private static int TOTAL_FILES = 1000;
private static int AUDIT_QUANTITY = 10;
private static int TIME_IN_SECONDS_FOR_ALL_FILES = 10;
private Random random = new Random();
private Deque<String> stack = new ArrayDeque<String>();
private boolean finished;
public static void main(String[] args) throws InterruptedException {
new ProbabilisticSelection().test();
}
private void test() throws InterruptedException {
Instant begin = Instant.now();
Runnable pushTask = () -> {
while (!finished) {
int next = random.nextInt(TOTAL_FILES);
String item = "File: " + next;
stack.push(item);
if (Duration.between(begin, Instant.now()).getSeconds() >= TIME_IN_SECONDS_FOR_ALL_FILES) {
finished = true;
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Runnable pullTask = () -> {
int itemNumber = 1;
while (itemNumber <= AUDIT_QUANTITY && !finished) {
String poll = stack.poll();
if (requirementsFunction(poll) &&
probabilityFunction(itemNumber, Duration.between(begin, Instant.now()))) {
System.out.println(itemNumber++ + ": "+ poll);
}
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
finished = true;
Duration delta = Duration.between(begin, Instant.now());
System.out.println();
System.out.println("Retrieved files: " + (itemNumber - 1) + ", should be, " + AUDIT_QUANTITY);
System.out.println("Time taken: " + delta.getSeconds() + ", should be, " + TIME_IN_SECONDS_FOR_ALL_FILES);
};
new Thread(pullTask).start();
new Thread(pushTask).start();
}
private boolean requirementsFunction(String item) {
return item != null && item.endsWith("0");
}
private boolean probabilityFunction(int itemNumber, Duration delta) {
double limit = ((double)(AUDIT_QUANTITY-itemNumber)/(double)AUDIT_QUANTITY + 1); // probability goes down as number of items goes up
double tension = (double)TIME_IN_SECONDS_FOR_ALL_FILES/((double)delta.getSeconds() + 1); // probablity goes up as time nears the end
if (tension == 1) {
return true;
}
double prob = limit * tension * 100;
int rand = random.nextInt(1000);
return prob > rand;
}
}
Algorithm is called Reservoir_sampling, which guarantees fair sampling of k items from some large and unknown N. Hereis Java code
I am beginner in programming and Java, and this is my first multi-core program. The problem is that my program never uses more than 13% of my CPU. I do not know if I do it in the right way or not.
How do I compute faster and use more CPU resources?
My program consists of three class:
The "main class that instantiates the Work object with a number of threads
A "T1" class that extends Thread and contains the work to be performed
A "Work" class that launches the desired thread numbers and displays the time taken by all threads to perform the work
Here is the code of my Main class:
public static void main(String[] args) {
System.out.println("Number of CPUs available = " + Runtime.getRuntime().availableProcessors()); //Display the number of CPUs available
int iteration = 100000000; // Define a number of itterations to do by all threads
/*
Instantiates each work with a different number of threads (1, 4, 8, 12, and 24)
*/
Work t1 = new Work(1);
Work t4 = new Work(4);
Work t8 = new Work(8);
Work t12 = new Work(12);
Work t24 = new Work(24);
/*
Launch the work for each thread with the specified number of iterations
*/
t1.goWork(iteration);
t4.goWork(iteration);
t8.goWork(iteration);
t12.goWork(iteration);
t24.goWork(iteration);
}
And here the Work class code:
public class Work {
static long time; // A variable that each thread increase by the time it takes to complete its task.
static int itterationPerThread; // A variable that stores the number of itterations Per Thread to do.
static int finish; // A variable that each thread incrase when it finish its task, used to wait until all thread has complete their task.
private int numberOfThreads; // The number of threads to launch.
/**
*
* The constructor, set the number Of threads to run
* #param numberOfThreads
*/
public Work(int numberOfThreads)
{
this.numberOfThreads = numberOfThreads; //Set the number of threads
}
/**
*
* A method that launch a specified number of thread in the constructor of the class, and distributes the a number of iteration of each thread.
* The method does nothing until each thread completes its task and print the time needed for all threads to complete their tasks.
* #param itterationPerThread
*/
public void goWork(int itterationPerThread)
{
finish = 0; //Reset the variable in the case that we call the method more than one time
time = 0; //Reset the variable in the case that we call the method more than one time
this.itterationPerThread = itterationPerThread/numberOfThreads; // Divide the given number of iterations by the number of threads specified in the constructor
for (int i=0; i<numberOfThreads; i++) //Launch the specified number of threads
{
new T1().run();
}
while (finish != numberOfThreads) //Do nothing until all thread as completed their task
{
}
System.out.println("Time for " + numberOfThreads + " thread = " + time + " ms"); //Display the total time
}
}
And finally my T1 class:
public class T1 extends Thread{
#Override
public void run()
{
long before = System.currentTimeMillis();
for (int i=0; i<Work.itterationPerThread; i++) //Get the thread busy with a number of itterations
{
Math.cos(2.1545); //Do something...
}
long after = System.currentTimeMillis(); //Compute the elapsed time
Work.time += after - before; //Increase the static variable in Work.java by the time elapsed for this thread
Work.finish++; // Increase the static variable in Work.java when the thread has finished its job
}
}
The programme gives me the following ouput on my machine (four physical cores and eight hyperthreaded):
Number of CPUs available = 8
Time for 1 thread = 11150 ms
Time for 4 thread = 4630 ms
Time for 8 thread = 2530 ms
Time for 12 thread = 2530 ms
Time for 24 thread = 2540 ms
According to my CPU this result seems correct, but my CPU usage never exceeds 13%.
I found the following Stack Overflow post, but I did not really find an answer to my question.
Instead of calling Thread.run(), which implements what your thread does, you should call Thread.start(), which will create a new thread and call run() on that new thread.
Now you are running run() on your main thread, without making a new thread. Since you have 13% CPU load, I expect you have 8 cores (meaning you have fully filled a single core).
Even better would be to create a custom implementation of the interface Runnable, instead of extending Thread. You can then run it on a thread as follows:
Thread t = new Thread(new MyRunnableTask());
t.start();
This is the common way because it gives you the flexibility (later on) to use more advanced mechanisms, such as ExecutorService.
EDIT:
As also noted in some of the comments. You are also changing the same variables (the static ones in Work) from several threads. You should never do this, because it allows for race conditions. For instance incrementing a variable can cause one, as explained here.
Thank you all for answering my question:
Yes, the JVM does not calculate the Math.cos(2.1545); on each iteration, so as said I've tried with Math.cos(i); on the original programme and there is a big difference!
And for the multi Thread, as said, I've created a custom implementation of the interface Runnable, instead of extending Thread and now use the Start(); method instead of run();
I now use the join method to wait until thread finish and remove the static variable.
Now the program use the full CPU load with the correct number of threads.
Just for information, here is my new code for the work class:
public class Work {
private Thread[] threadArray; //An array to store a specified number of new threads in the constructor
/**
*
* The constructor, set to the number Of threads to run
* #param numberOfThreads
*/
public Work(int numberOfThreads)
{
threadArray = new Thread[numberOfThreads];
}
/**
*
* A methode that launch a specified number of threads in the constructor of the class, and distributes the a number of iteration of each thread.
* the methode wait until each thread complete their task and print the time needed for all thread to complette their task.
* #param itterationForAllThread --> the total of itteration to do by all thread
*/
public void goWork(int itterationForAllThread)
{
long time = 0; // A variable used to compute the elapsed time
int itterationPerThread; // A variable that store the number of itterations Per Thread to do
itterationPerThread = itterationForAllThread/threadArray.length; //Divide the given number of itteration by the number of tread specified in the constructor
for(int i=0; i<threadArray.length; i++) //Launch the specified number of threads
{
threadArray[i] = new Thread(new T1(itterationPerThread)); //Create a new thread
threadArray[i].start(); //Start the job
}
long before = System.currentTimeMillis();
for (Thread thread : threadArray) //For each thread wait until it finish
{
try {
thread.join(); //Wait for the thread as finish
}
catch (InterruptedException ex)
{
ex.printStackTrace();
}
}
long after = System.currentTimeMillis();
time = after - before; //Compute the time elapsed
System.out.println("Time for " + threadArray.length + " Thread = " + time + " ms"); //Display the total time for the number of threads
}
}
And here the T1 class:
public class T1 implements Runnable{
private int iterrattionPerThread;
T1(int iterrattionPerThread)
{
this.iterrattionPerThread=iterrattionPerThread;
}
#Override
public void run()
{
for(int i=0; i<iterrattionPerThread; i++) //Get the thread busy with a number of iterations
{
Math.cos(i); //Do something that the JVM can not cache and need to be recaculated every iteration
}
}
}
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);
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();
}
I wrote a simple code that uses multiple threads to calculate number of primes from 1 to N.
public static void main (String[] args) throws InterruptedException
{
Date start;
start = new Date();
long startms = start.getTime();
int number_primes = 0, number_threads =0;
number_primes = Integer.parseInt(args[0]);
number_threads = Integer.parseInt(args[1]);
MakeThread[] mt = new MakeThread[number_threads];
for(int i=1;i<=number_threads;i++)
{
mt[i-1] = new MakeThread(i,(i-1)*(number_primes/number_threads),i*(number_primes/number_threads));
mt[i-1].start();
}
for(int i=1;i<number_threads;i++)
{
mt[i-1].join();
}
Date end = new Date();
long endms = end.getTime();
System.out.println("Time taken = "+(endms-startms));
}
}
As show in above, I want the final time taken to be displayed (just to measure performance for different inputs). However I noticed that when I enter a really big value of N and assign only 1 or 2 threads, the scheduler seems to override the join functionality (i.e the last print statement is displayed before other threads end). Is the kernel allowed to do this? Or do I have some bug in my code?
P.S: I have only shown a part of my code. I have a similar System.out.println at the end of the function that the newly forked threads call.
Your loop is the problem.
for(int i=1;i<number_threads;i++)
{
mt[i-1].join();
}
Either you change the condition to <= or you make a less cryptic loop like this:
for(int i=0; i < number_threads;i++){
mt[i].join();
}
Or a for each loop:
for(MakeThread thread : mt)
thread.join();
Provided you correct your loop which calls join on all threads as shown below
for(int i=0;i<number_threads;i++)
{
mt[i].join();
}
there is no way that the last print line may get invoked before all threads ( as specified in the loop ) finish running and join the main thread. Scheduler cannot make any assumptions with this semantics. As pointed by Thomas , the bug is there in your code that does not call join on the last thread ( which therefore does not complete before the last print is called ).