I have developed code in Java for generating ten random numbers from a range 0 to 99. The problem is I need to generate a random number for every 2 min. I am new to this area and need your views.
This example adds a random number to a blocking dequeue every two minutes. You can take the numbers from the queue when you need them. You can use java.util.Timer as a lightweight facility to schedule the number generation or you can use java.util.concurrent.ScheduledExecutorService for a more versatile solution if you need more sophistication in the future. By writing the numbers to a dequeue, you have a unified interface of retrieving numbers from both facilities.
First, we set up the blocking queue:
final BlockingDequeue<Integer> queue = new LinkedBlockingDequeue<Integer>();
Here is the setup with java.utilTimer:
TimerTask task = new TimerTask() {
public void run() {
queue.put(Math.round(Math.random() * 99));
// or use whatever method you chose to generate the number...
}
};
Timer timer = new Timer(true)Timer();
timer.schedule(task, 0, 120000);
This is the setup with java.util.concurrent.ScheduledExecutorService
ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
Runnable task = new Runnable() {
public void run() {
queue.put(Math.round(Math.random() * 99));
// or use whatever method you chose to generate the number...
}
};
scheduler.scheduleAtFixedRate(task, 0, 120, SECONDS);
Now, you can get a new random number from the queue every two minutes. The queue will block until a new number becomes available...
int numbers = 100;
for (int i = 0; i < numbers; i++) {
Inetger rand = queue.remove();
System.out.println("new random number: " + rand);
}
Once you are done, you can terminate the scheduler. If you used the Timer, just do
timer.cancel();
If you used ScheduledExecutorService you can do
scheduler.shutdown();
You have two requirements which are unrelated:
Generate random numbers
Perform the task every 2 minutes.
To do anything every 2 minutes you can use a ScheduledExecutorService.
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Random;
import javax.swing.JFrame;
import javax.swing.Timer;
public class TimerExample {
Random rand = new Random();
static int currRand;
TimerExample() {
currRand = rand.nextInt(99);
ActionListener actionListener = new ActionListener() {
public void actionPerformed(ActionEvent actionEvent) {
currRand = rand.nextInt(99);
}
};
Timer timer = new Timer(2000, actionListener);
timer.start();
}
public static void main(String args[]) throws InterruptedException {
TimerExample te = new TimerExample();
while( true ) {
Thread.currentThread().sleep(500);
System.out.println("current value:" + currRand );
}
}
}
EDIT: Of course you should set 2000 in new Timer(2000, actionListener); to 120 000 for two minutes.
You can schedule your program to be run once every two minutes using whatever scheduling features are available to you in your target environment (e.g., cron, at, Windows Scheduled Tasks, etc.).
Or you can use the Thread#sleep method to suspend your application for 2,000ms and run your code in a loop:
while (loopCondition) {
/* ...generate random number... */
// Suspend execution for 2 minutes
Thread.currentThread().sleep(1000 * 60 * 2);
}
(That's just example code, you'll need to handle the InterruptedException and such.)
I'm not entirely sure I understand the problem. If you wish to generate a different random number every two minutes, simply call your rnd function every two minutes.
This could be as simple as something like (pseudo-code):
n = rnd()
repeat until finished:
use n for something
sleep for two minutes
n = rnd()
If you want to keep using the same random number for two minutes and generate a new one:
time t = 0
int n = 0
def sort_of_rnd():
if now() - t > two minutes:
n = rnd()
t = now()
return n
which will continue to return the same number for a two minute period.
Related
This question already has answers here:
How to schedule a periodic task in Java?
(13 answers)
Closed 2 years ago.
how to call method multiple times within given time java
Ex: if I want to call method A() for 3 times within 120 seconds. these two values should be configurable
You should take a look at Timers in Java. Documentation of Java SE 8 of Timer can be found here.
Here's an example: You can adjust the delay, period to your own preference.
// Initialize the Timer, this is the actual function that will start a TimerTask
private static final Timer timer = new Timer();
// Initialize the TimerTask, this is like the recipe for the Timer
private static final TimerTask task = new TimerTask() {
// Create a variable to keep track how many times we have ran this code
private int count = 0;
// Function that will be ran in the TaskTimer
public void run() {
// Your Code goes here
// Add to the amount of times we have ran this code
count++;
// If the count has reached 3...
if( count == 3 ) {
// we cancel the task
task.cancel();
}
}
};
// Using the TimerTask
public static void main( String[] args ) {
// Set the delay (adjust this to your own needs)
long delay = 2000;
// Set the period (adjust this to your own needs)
long period = 5000;
// Schedule the TimerTask
timer.schedule(task, delay, period);
}
It's always a good idea to take a look if your dependency has it's own set of Timer and AsyncTimer, as sometimes it's more efficient to use there's.
I want to Schedule a job to run at multiple of 2 seconds, which is 2,4,8,16,32 seconds. Second fire should happen after two seconds of completion of first fire, Third fire should happen after 4 seconds of completion of second fire and so on. The next fire is based on status we get from previous fire, based on which it will be decided whether we need to trigger next fire or not.
Can somebody tell me how can I use quartz scheduler to achieve this?
If I use SimpleTrigger.withIntervalInSeconds(2) it runs a job after every 2 seconds where as I want time interval should be increased with multiple of 2 in every firing.
Perhaps you could forget trying to set up a single trigger, but use multiple triggers. My Java is not good in this area, so this is in pseudocode:
delay = 2
repeat
TriggerOnceAfter(delay)
delay <- delay * 2
WaitUntilTriggered()
until (finished)
I am not sure how to implement the WaitUntilTriggered() method; you my need to add a signalling flag to the triggered code for WaitUntilTriggered() to look at.
That will give delays of 2, 4, 8, ...
This is a simplified implementation that will invoke a Runnable at the requested schedule:
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
public class Tasker {
private int numberOfRuns; //how many times job executed
private int timeBetweenRuns;//seconds
Tasker(int numberOfRuns){
this.numberOfRuns = numberOfRuns;
timeBetweenRuns = 2;
execute();
}
private void execute() {
for (int counter = 0; counter < numberOfRuns ; counter++) {
CountDownLatch latch = new CountDownLatch(1);
Job job = new Job(latch, timeBetweenRuns);
job.run();
try {
latch.await();
TimeUnit.SECONDS.sleep(timeBetweenRuns);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
timeBetweenRuns *=2;
}
}
public static void main(String[] args){
new Tasker(5);
}
}
class Job implements Runnable {
private int seconds;
private CountDownLatch latch ;
Job(CountDownLatch latch , int seconds){
this.latch = latch;
this.seconds = seconds;
}
#Override
public void run() {
System.out.println("Job runs "+ seconds +" after previous one");
latch.countDown();
}
}
I have client-server application in which i need to measure the rate of request arrival per second(Request rate). For this, i have a timer object that activates after every seconds, reads a synchronized counter and then sets it to zero. The counter increments on each request arrival.I used following code to detect request rate. There are so many other threads and timers in my application running.The problem is "due to the inaccuracy of timers i am not getting the perfect request rate". Is there any alternative of measuring request rate other than using timers.
public class FrequencyDetector extends TimerTask {
RequestCounter requestCounter;
FrequencyHolder frequencyHolder;
public FrequencyDetector(RequestCounter requestCounter,FrequencyHolder frequencyHolder){
this.frequencyHolder=new FrequencyHolder();
this.frequencyHolder=frequencyHolder;
}
#Override
public void run() {
int newFrequency=requestCounter.getCounter();
frequencyHolder.setFrequency(newFrequency);
requestCounter.setCounterToZero();
//calls to other fuctions
}
}
Instead of checking counter per unit time you can check time per unit counter. That will probably give you more accurate results. Algorithm is given below.
Increment counter on every request.
When counter reaches a certain FIXED_LIMIT calculate frequency by frequency=FIXED_LIMIT/duration since last record
Reset the counter and start with step 1
However this will record frequency at unpredictable intervals and if frequency of request decreases the duration between successive records will increase.
To handle it we can implement an adaptive algorithm, algorithm is given below.
Increment the counter on every request.
When counter reaches a certain ADAPTIVE_LIMIT record frequency as frequency=ADAPTIVE_LIMIT/duration since last record
Change ADAPTIVE_LIMIT as ADAPTIVE_LIMIT=frequency * DESIRED RECORD INTERVAL
Reset counter and start with step 1.
Above algorithm will reset the limit based on frequency last recorded. It's given that it will not be recording at optimal intervals but it will be pretty close.
Also it will give you highly accurate frequencies as it does not depend on any scheduled thread.
Following is an implementation of such an adaptive counter.
import java.util.Random;
import java.util.concurrent.atomic.AtomicLong;
public class TestCounter {
//Keep initial counterInterval to a small value otherwise first record may take long time
final AtomicLong counterInterval = new AtomicLong(10);
AtomicLong requestCounter = new AtomicLong();
volatile long lastTime;
/**OPTIMAL_DURATION is the duration after which frequency is expected to be recorded
* Program adaptively tries to reach this duration
*/
static final double OPTIMAL_DURATION = 1.0; // 1 second
static final Random random = new Random();
public static void main(String[] args) {
System.out.println("Started ");
TestCounter main = new TestCounter();
for(int i = 0; i < 1000; i++) {
main.requestArrived();
}
}
/*
* Simulating requests
*/
public void requestArrived() {
printCounter();
try {
Thread.sleep(random.nextInt(100));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//This will be in some Utility class
private void printCounter() {
requestCounter.incrementAndGet();
long currentTime = System.nanoTime();
long currentInterval = counterInterval.get();
if(requestCounter.get() > currentInterval) {
if(lastTime != 0) {
long timeDelta = currentTime - lastTime;
long frequency = (long)(currentInterval / (timeDelta / 1e9));
System.out.printf("time=%.2f, frequency=%d\n", (timeDelta / 1e9), frequency);
//updating the currentInterval for the miss
long newCounterInterval = (long)(frequency * OPTIMAL_DURATION);
counterInterval.set(newCounterInterval);
}
requestCounter.set(0);
lastTime = currentTime;
}
}
}
Output
Started
time=0.54, frequency=18
time=0.98, frequency=18
time=1.01, frequency=17
time=0.96, frequency=17
time=0.99, frequency=17
time=0.85, frequency=19
time=0.96, frequency=19
time=0.82, frequency=23
time=1.08, frequency=21
time=0.98, frequency=21
time=0.94, frequency=22
time=1.06, frequency=20
time=1.07, frequency=18
time=0.99, frequency=18
time=0.98, frequency=18
time=1.02, frequency=17
time=0.92, frequency=18
time=0.92, frequency=19
time=0.89, frequency=21
time=0.82, frequency=25
time=1.31, frequency=19
time=1.02, frequency=18
What is the difference between these 2 methods of Timer class :
schedule(TimerTask task, long delay, long period)
and
scheduleAtFixedRate(TimerTask task, long delay, long period)
Documentation doesn't make the difference between them clear.
The documentation does explain the difference:
schedule:
In fixed-delay execution, each execution is scheduled relative to the actual execution time of the previous execution. If an execution is delayed for any reason (such as garbage collection or other background activity), subsequent executions will be delayed as well.
So, suppose the delay is 5 seconds, and each task takes 2 seconds, you would get
TTWWWTTWWWTTWWWTT
where T means 1 second for the task execution, and W means 1 second waiting.
But now suppose that a long GC (represented by a G) happens and delays the second task, the third one will start 5 seconds after the start of the second one, as if the long GC didn't happen:
TTWWWGGTTWWWTTWWWTT
The third task starts 5 seconds after the second one.
scheduleAtFixedRate:
In fixed-rate execution, each execution is scheduled relative to the scheduled execution time of the initial execution. If an execution is delayed for any reason (such as garbage collection or other background activity), two or more executions will occur in rapid succession to "catch up.".
So, with the same delay as above, and the same GC, you would get
TTWWWGGTTWTTWWWTT
The third task task starts 3 seconds instead of 5 after the second one, to catch up.
Thanks #Nizet's answer, I have written a sample code for some people who want to practice and learn.
import java.util.Timer;
import java.util.TimerTask;
public class TimerTest {
public static void main(String args[]){
TimerTest.DelayTask task = new DelayTask();
Timer timer = new Timer();
/**
* Use schedule or scheduletAtFixedrate and check the printed result
*/
timer.schedule(task, 0, 5000);
//timer.scheduleAtFixedRate(task, 0, 5000);
}
public static boolean stop = false;
public static void delayOneSec(String status){
try{
System.out.print(status);
Thread.sleep(1000);
}catch(Exception e){
e.printStackTrace();
}
}
static class DelayTask extends TimerTask{
int count = 2;
#Override
public void run() {
// TODO Auto-generated method stub
stop = true;
for(int i = 0; i < count; i++){
TimerTest.delayOneSec("T");
}
if(count == 2){
count = 6;
}else{
count = 2;
}
stop = false;
new PrintW().start();
}
}
static class PrintW extends Thread{
#Override
public void run(){
while(!stop){
TimerTest.delayOneSec("W");
}
}
}
}
The task itself will repeat to take 2 seconds or 6 seconds. Let's see the result of each scenario.
When using timer.schedule(task, 0, 5000);, the output is TTWWWTTTTTTTTWWWTTTTTTTTWWWTTTTTTTT. As you can see, the timer follow the rules like below, wait till period time outs if task finishes in time, launch next task immediately if current task lasts more than period.
When using timer.scheduleAtFixedRate(task, 0, 5000);, the output is TTWWWTTTTTTTTWWTTTTTTTTWWTTTTTTTTWWTTTTTTTTWWTTTTTTTTWWTTTTTTTT. Things are a little different now. The javadoc
two or more executions will occur in rapid succession to "catch up."
takes effect here. As you can see, ignoring the first TTWWW, every two tasks will print TTTTTTTTWW and it lasts 10 seconds(two periods).
Let's dig into the source code of Timer.
public void schedule(TimerTask task, Date firstTime, long period) {
if (period <= 0)
throw new IllegalArgumentException("Non-positive period.");
sched(task, firstTime.getTime(), -period);
}
public void scheduleAtFixedRate(TimerTask task, long delay, long period) {
if (delay < 0)
throw new IllegalArgumentException("Negative delay.");
if (period <= 0)
throw new IllegalArgumentException("Non-positive period.");
sched(task, System.currentTimeMillis()+delay, period);
}
As you can see, the period is transferred to negative value in schedule method. Let's see what's the difference when scheduling it.
The below code is in the mainloop of TimerThread,
currentTime = System.currentTimeMillis();
executionTime = task.nextExecutionTime;
if (taskFired = (executionTime<=currentTime)) {
if (task.period == 0) { // Non-repeating, remove
queue.removeMin();
task.state = TimerTask.EXECUTED;
} else { // Repeating task, reschedule
queue.rescheduleMin(
task.period<0 ? currentTime - task.period
: executionTime + task.period);
}
}
}
It's where magic happens, for schedule method, the next task execution time is based on the currentTime which is calculated right before the this task runs. That means, every task's execution time only be related with previous task starts time.
I need to create a java function that will only run for 30 minutes, and at the end of the 30 minutes it executes something. But it should also be able to self terminate before the given time if the right conditions are met. I don't want the function to be sleeping as it should be collecting data, so no sleeping threads.
Thanks
Use: Timer.schedule( TimerTask, long )
public void someFunctino() {
// set the timeout
// this will stop this function in 30 minutes
long in30Minutes = 30 * 60 * 1000;
Timer timer = new Timer();
timer.schedule( new TimerTask(){
public void run() {
if( conditionsAreMet() ) {
System.exit(0);
}
}
}, in30Minutes );
// do the work...
.... work for n time, it would be stoped in 30 minutes at most
... code code code
}
Get the start time with System.currentTimeMillis(), calculate the time when to stop and check the current time every now and then while you're collecting the data you want to collect. Another way would be to decouple the timer and the data collecting, so that each of them could run in their own threads.
For a more specific answer, it would be helpful if you would tell what data you are collecting and how you are collecting it.
Something like this will work:
long startTime = System.currentTimeMillis();
long maxDurationInMilliseconds = 30 * 60 * 1000;
while (System.currentTimeMillis() < startTime + maxDurationInMilliseconds) {
// carry on running - 30 minutes hasn't elapsed yet
if (someOtherConditionIsMet) {
// stop running early
break;
}
}
The modern java.util.concurrent way would be using ExecutorService. There are several invoke methods taking a timeout.
Here's a kickoff example:
public static void main(String args[]) throws Exception {
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.invokeAll(Arrays.asList(new Task()), 30, TimeUnit.MINUTES);
executor.shutdown();
}
where Task look like this:
public class Task implements Callable<String> {
#Override
public String call() {
// Just a dummy long running task.
BigInteger i = new BigInteger("0");
for (long l = 0; l < Long.MAX_VALUE; l++) {
i.multiply(new BigInteger(String.valueOf(l)));
// You need to check this regularly..
if (Thread.interrupted()) {
System.out.println("Task interrupted!");
break; // ..and stop the task whenever Thread is interrupted.
}
}
return null; // Or whatever you'd like to use as return value.
}
}
See also:
Lesson: Concurrency