Load Test using Java - timer task vs scheduler - java

I need to execute a load test using Java in which one of the test strategies require x threads to be fired of every y period of time for z minutes and thereafter have a constant totalThread amount of threads running for the load test duration (eg with a total of 100 threads, start 10 threads at 5 second intervals until all 100 threads have started, and continue to keep all 100 threading running (once it has finished execution it should restart) for the specified duration of the test, say one hour)
I have attempted to use the timer task but it seems limiting, would thread pool scheduler be a better option? What would be the best approach?
public class MyTask extends TimerTask{
public void run() {
System.out.println("STARTING THREAD "+ counter +" "+ new Date());
//execute test
counter++;
if (counter > maxIterations) {
MyTask.this.cancel();
return;
}
}
List<TimerTask> MyTaskList = new ArrayList<TimerTask>();
for (int i = 1 ; i <= threadsPerIteration ; i++) {
TimerTask MyTimerTask = new MyTask(NumberOfIterations);
MyTaskList.add(MyTimerTask);
timer.schedule(MyTimerTask, initialDelayMilli, threadDelayMilli);
}
Thank You

Don't use a TimerTask for each thread. Instead, use a single TimerTask, that fires once per interval, with your example numbers once every 5 seconds.
Each of the first 10 times the TimerTask fires, it spawns off 10 threads. On each subsequent firing, it checks for the number of active threads, and spawns off enough new threads to bring the total to 100, until the end of your test.

Thanks for the help, i decided to use the threadpool executor together with the timertask class as follows:
I used the Executors.newScheduledThreadPool(int x) method to control the amount of threads able to run concurrently, together with a timer task that is set to increase the threadpool size every y amount of time :
TimerTask DelayTimerTask = new TimerTask() { //task to increase threadpool size
public void run() {
MyExecutor.setCorePoolSize(i * incrementAmount); //timer task increments threadpool size by threadPoolIncrement
i++;
}
};
timer.scheduleAtFixedRate(DelayTimerTask,0,intervalLength);
in this way the amount of concurrent threads will increase by incrementAmount every intervalLength.

Related

Accurate thread loop. Run a task with precise interval

I want my thread to perform an action 4 or 16 times per bpm (beats per minute). This timer is not 100% accurate, after a few seconds it desynchronizes from the metronome I found on youtube, and it gets a little slower than it should.
bpm = (float) my music bpm;
thread = new Thread(()->{
long now ;
long total ;
while (true) {
long bpmTime = (long) ((1000000000*60d)/(bpm*16));
now = System.nanoTime();
bpmTick(); //<-- my task
try {
total = System.nanoTime() - now;
if(total > bpmTime) {
continue;
}
Thread.sleep((bpmTime - (System.nanoTime() - now)) / 1000000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
thread.start();
I also tried:
Thread.sleep((long)(1000*(60.0/bpm)));
but the same problem occurs
In short, I need a metronome.
Thanks in advance.
What you want to use is a ScheduledExecutorService instance instead. This class can repeat the task in a Thread repeatedly at a fixed rate. The class has a method called scheduleAtFixedRate(task, intialDelay, DelayBetweenExecutions,TimeUnit) just for this purpose.
When the initial delay is set to 0 the task will run as soon as scheduleAtFixedRate is called and will continue doing so until you call shutdown() or shutdownNow() on the service. Here's an example that uses some of your code:
ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
int timesPerBPM = 16;
long bpmTime = 900; //or whatever the outcome of your formula is.
Thread thread = new Thread(()->{
for (int i = 0; i < timesPerBPM; i++) //do task 16 times
bpmTick(); //<-- my task
});
executorService.scheduleAtFixedRate(thread, 0, bpmTime, TimeUnit.MILLISECONDS); //This will start immediately because initialDelay is 0.
executorService.shutdown(); //Always shutdown service when done to avoid memory leaks.
The executorService in the below code will run bpmTick() 16 times every 900 milliseconds. If it takes longer then 900 milliseconds to run bpmTick() 16 times the service will wait for the current task to complete until it starts the next repetition. So to keep things synchronized the 16 bpmTick() must always finish within bpmTime milliseconds. If you want to guarantee a 150 millisecond pause between threadtask executions regardless of how long it takes to execute a task then you should use the method scheduleWithFixedDelay() instead.
If you want the service to repeat the task every minute instead of every 900 milliseconds then it is best to change bpmTime to 1 and TimeUnit.MILLISECONDS to TimeUnit.MINUTES.

Java - Run tasks in varying time intervals

This question is for a college assignment.
I want to run a block of code every n*2 seconds (e.g. wait 1 second and run and wait 2 seconds and run and wait 4 seconds and run, etc) up to 5 times.
I currently have something like this.
int timer = 1000;
int tryCounter = 0;
while( !condition() && counter < 5){
doTask();
Thread.sleep(timer);
timer *= 2;
counter++;
}
Although this works, my grade benefits from not using Thread.sleep(). I figured out using a ScheduledThreadPoolExecutor with a fixed rate would be one way to go but I cannot get it to work due to the fact that the interval is not actually fixed.
This is for a theoretical Distributed System with high concurrency capabilities so what matters is the high scalability.
I could get away with Thread.sleep() if there was really no benefit or a viable way of doing this by writing it on my report. So does anyone have any insight on this?
It is possible to schedule tasks with ScheduledExecutorService combined with some logic. The .schedule argument lets you specify a time unit to use. You can declare a variable that can handle the increment you are trying to do.
int timer = 1000;
ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
Runnable runnable = new Runnable() {
public void run()
{
//Move your code you want to implement here
}
};
//Increment your variable
while(!condition()) {
for(int i = 0; i < 5; i++) {
service.schedule(runnable, timer, TimeUnit.SECOND);
timer *= 2;
}
}
Moving your code execution within the runnable block and then scheduling it within a for loop where the timer is incremented should accomplish the effect you are going for. Hope that helps!

Java execute method from within a loop every few seconds

I have a Thread that runs in my test app with a while loop inside the thread. While the while loop is running i want to execute a method from within this while loop every 30 seconds. Inside the while loop, don't want to sleep the thread or stop the loop, it must run and every 30 seconds call the method.
Thread myThread = new Thread() {
#Override
public void run() {
//my code that runs with a loop
//while loop here that runs and needs to execute method every 30 seconds, if condition met continue else break;
};
myThread.start();
}
To wait, you can use
Thread.sleep(milliseconds);
For documentation, see here
If you wait for 30 seconds in your loop, it happens every 30 seconds + execution time of your function. As long as your function call only takes milliseconds this is as precise as doing it in a more complex way.
If you want your loop to keep running but you do not want to launch a new Thread, you can use the current Time:
long lastCall = 0;
while(bla) {
if(System.currentTimeMillis() - lastCall > 30000) {
lastCall = System.currentTimeMillis();
callTheFunction();
}
}
Place it where thread is executed:
Thread.sleep(30000);

Fibonacci on Java ExecutorService runs faster sequentially than in parallel

I am trying out the executor service in Java, and wrote the following code to run Fibonacci (yes, the massively recursive version, just to stress out the executor service).
Surprisingly, it will run faster if I set the nThreads to 1. It might be related to the fact that the size of each "task" submitted to the executor service is really small. But still it must be the same number also if I set nThreads to 1.
To see if the access to the shared Atomic variables can cause this issue, I commented out the three lines with the comment "see text", and looked at the system monitor to see how long the execution takes. But the results are the same.
Any idea why this is happening?
BTW, I wanted to compare it with the similar implementation with Fork/Join. It turns out to be way slower than the F/J implementation.
public class MainSimpler {
static int N=35;
static AtomicInteger result = new AtomicInteger(0), pendingTasks = new AtomicInteger(1);
static ExecutorService executor;
public static void main(String[] args) {
int nThreads=2;
System.out.println("Number of threads = "+nThreads);
executor = Executors.newFixedThreadPool(nThreads);
Executable.inQueue = new AtomicInteger(nThreads);
long before = System.currentTimeMillis();
System.out.println("Fibonacci "+N+" is ... ");
executor.submit(new FibSimpler(N));
waitToFinish();
System.out.println(result.get());
long after = System.currentTimeMillis();
System.out.println("Duration: " + (after - before) + " milliseconds\n");
}
private static void waitToFinish() {
while (0 < pendingTasks.get()){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
executor.shutdown();
}
}
class FibSimpler implements Runnable {
int N;
FibSimpler (int n) { N=n; }
#Override
public void run() {
compute();
MainSimpler.pendingTasks.decrementAndGet(); // see text
}
void compute() {
int n = N;
if (n <= 1) {
MainSimpler.result.addAndGet(n); // see text
return;
}
MainSimpler.executor.submit(new FibSimpler(n-1));
MainSimpler.pendingTasks.incrementAndGet(); // see text
N = n-2;
compute(); // similar to the F/J counterpart
}
}
Runtime (approximately):
1 thread : 11 seconds
2 threads: 19 seconds
4 threads: 19 seconds
Update:
I notice that even if I use one thread inside the executor service, the whole program will use all four cores of my machine (each core around 80% usage on average). This could explain why using more threads inside the executor service slows down the whole process, but now, why does this program use 4 cores if only one thread is active inside the executor service??
It might be related to the fact that the size of each "task" submitted
to the executor service is really small.
This is certainly the case and as a result you are mainly measuring the overhead of context switching. When n == 1, there is no context switching and thus the performance is better.
But still it must be the same number also if I set nThreads to 1.
I'm guessing you meant 'to higher than 1' here.
You are running into the problem of heavy lock contention. When you have multiple threads, the lock on the result is contended all the time. Threads have to wait for each other before they can update the result and that slows them down. When there is only a single thread, the JVM probably detects that and performs lock elision, meaning it doesn't actually perform any locking at all.
You may get better performance if you don't divide the problem into N tasks, but rather divide it into N/nThreads tasks, which can be handled simultaneously by the threads (assuming you choose nThreads to be at most the number of physical cores/threads available). Each thread then does its own work, calculating its own total and only adding that to a grand total when the thread is done. Even then, for fib(35) I expect the costs of thread management to outweigh the benefits. Perhaps try fib(1000).

Scheduling a task from within a task - good practice?

I have a daily 'Dinner Ready' event that is supposed to happen at say at 15:00, but sometimes it is delayed and happens at 15:05, or 16.20 etc.
I want to setup a task 'Check Dinner Status' that is run periodically, starting 3 hours before the expected Dinner Ready event, and running at defined intervals until Dinner is Ready. The interval between how often I check dinner gets shorter and shorter the closer I get to dinner time.
What is the best way to setup this schedule? It is fairly simple to setup the next CheckDinnerTask from within the one that is just running. But is this a good practice?
The code below is based on Spring Scheduling, but I'm open to any scheduling framework.
scheduler.schedule(new CheckDinnerTask(), new CronTrigger("* 0 12 * * *"));
public class CheckDinnerTask() implements Runnable {
run() {
if (isDinnerReady() == false)
{
// Find out how long until scheduled dinner and
int mins = getMinutesToExpectedDinnerTime();
mins /= 2;
if (mins < 5)
mins = 5;
// Reschedule this task from here?
scheduler.scheduleWithFixedDelay(new CheckDinnerTask(), mins*60*1000);
}
else
{
eatDinner();
}
}
}

Categories

Resources