I have a requirement that, with in a time duration (suppose it is 50 sec, the time might be dynamic) i have to fetch some data from a server.
At the same time every 10sec (in between this 30 sec), I have to send some keys to server.
for that iam using below code....but it is not working
public static void main(String[] args) {
long startTime = System.currentTimeMillis();
long duration = (50 * 1000);
do {
// RESEt request call code goes here..
/////
//////
System.out.println("Rest request");
java.util.Timer t = new java.util.Timer();
java.util.TimerTask task = new java.util.TimerTask() {
#Override
public void run() {
//Sending key every 10 sec
RemoteKey.send(PageUp);
}
};
t.schedule(task, 0, (10 * 1000));
// This do while loop will execute 50 sec
} while ((System.currentTimeMillis() - startTime) < duration);
}
Why not schedule once, and cancel itself?
long duration=whatever;
java.util.Timer timer = new java.util.Timer();
java.util.TimerTask task = new java.util.TimerTask() {
long t0=System.currentTimeMilis(); // or set it upon scheduling;
#Override
public void run() {
//this will stop the task from executing in future.
if((System.currentTimeMillis() - t0) >= duration) { this.cancel(); return;}
// do actual work
RemoteKey.send(PageUp);
}
};
timer.scheduleAtFixedRate(task,initialDelay,delayBetweenActions);
More modern approach would be to use ScheduledExecutorService.
I think you should use RxJava and Job Scheduler to schedule the task at particular interval.
For example:
Observable.interval(50, TimeUnit.SECONDS)
.doOnNext(n -> performYourtask())
.subscribe();
This would be the optimal approach, using the modern ScheduledExecutor
As the timespan of, say 50 seconds, is ruled by the fetching operation, and that operation is synchronous, you'll just have to wait for it to end.
// Start the executor, scheduling your Runnable Task to run every 10 seconds
executorService.scheduleAtFixedRate(
() -> {
// Send your data
}, 0, 10, TimeUnit.SECONDS);
// Fetch data from your Server.
// That's a blocking operation, which, let's say will take 50 seconds
// Stop the Executor as the time is over
executorService.shutdown();
The Executor can be created via Factory method.
Executors.newScheduledThreadPool(5); // For multiple, concurrent threads
Executors.newSingleThreadScheduledExecutor(); // For a synchronous "queue"
Related
I am attempting to executing a email job for every minute. Job has 5 services. Each 5 services should run in parallel.
Using ExecutorService :
ExecutorService service = null;
if (serviceMap != null && serviceMap.size() > 0) {
for (;;) {
service = Executors.newFixedThreadPool(serviceMap.size()); // Here Service Map size will be 5
for (Map.Entry entry : serviceMap.entrySet()) {
service.submit(new EmailService(conn, mailParam));
}
service.shutdown();
service.awaitTermination(1, TimeUnit.MINUTES);
}
}
Using ScheduledExecutorService :
ScheduledExecutorService scheduledExecutorService = null;
if (serviceMap != null && serviceMap.size() > 0) {
scheduledExecutorService = Executors.newFixedThreadPool(serviceMap.size()); // Here Service Map size will be 5
for (Map.Entry entry : serviceMap.entrySet()) {
ScheduledFuture scheduledFuture =
scheduledExecutorService.schedule(new EmailService(conn, mailParam),
60,
TimeUnit.SECONDS);
System.out.println("result = " + scheduledFuture.get());
}
scheduledExecutorService.shutdown();
}
If I use ExecutorService, for every minute I shutdown the service and execute the service again. Is it all right?
If I use ScheduledExecutorService, I couldn't be able to write code to execute service in parallel and couldn't be able to run the job for every minute.
Above is my code snippet. Please help me to resolve it.
First of all, you should call newScheduledThreadPool() that creates ScheduledExecutorService, which is the correct scheduling executor service.
Then you should use [scheduleAtFixedRate][1] method to schedule a task every minute with initial delay 60 seconds.
ScheduledExecutorService scheduledExecutorService = null;
if (serviceMap != null && serviceMap.size() > 0) {
scheduledExecutorService = Executors.newScheduledThreadPool(serviceMap.size()); // Here Service Map size will be 5
for (Map.Entry entry : serviceMap.entrySet()) {
scheduledExecutorService.scheduleAtFixedRate(new EmailService(conn, mailParam),
60,
60,
TimeUnit.SECONDS);
}
}
Good question !!
You have to separate it as two classes.
One is to start scheduler. Another one for execute the service which implements Callable or Runnable interface.
scheduledExecutorService.schedule() is different from service.submit().
schedule() is used to schedule a process whereas submit is used for submitting the services.
Start Scheduler Class :
public static void main(String[] args) {
Class2 runnable = new Class2() {
#Override
public void run() {
// call method that has ExecuteService Impl
}
};
ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
service.scheduleAtFixedRate(runnable, 0, 60, TimeUnit.SECONDS);
}
I'm working on a program that needs to inspect multiple resources in parallel and periodically:
public class JobRunner {
private final SensorService sensorService;
private ScheduledExecutorService executor = Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors());
public void run() {
sensorService.finalAll().forEach(sensor -> {
Runnable task = () -> {
// read and save new data to log
List<Double> data = sensor.fetchNewData();
this.save(data);
};
// execute every 10 sec
executor.scheduleWithFixedDelay(task, 0, 10, TimeUnit.SECONDS);
});
}
public void save(List<Double> data) {
// ...
}
}
The findAll call returns a list of about 50 sensors, but when I run the program I see that while all sensors are queried on the first period, only 2-3 are called on subsequent executions (e.g - at 20 sec, 30 sec, etc). I'm thinking that since some sensors return faster than others, they complete the task's waiting cycle earlier and are grabbed by the next thread in the pool, thereby starving the other tasks that are slower to finish.
How can I ensure all tasks (sensors) are given equal treatment? What's are some best practices here; should I use a job queue or a different concurrency mechanism? Thanks.
In your code there are N=count service.findAll() timers, which makes debugging and testing more difficult. Moreover there is no guarantee that old task will be executed and not overtaken by the new one in reasonable time. What if you
Use single timer which triggers sensors check 10s after last all sensors check completed
Go through sensors concurrently when check is triggered by the timer
Please, see the next code as an example. It prints 50 integers every 10 seconds and EOL afterwards. Parallelism is achieved with Stream API
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
executor.scheduleWithFixedDelay(new Runnable() {
#Override
public void run() {
IntStream.range(0, 50).parallel().forEach(i -> System.out.print(i + " "));
System.out.println();
}
}, 0, 10, TimeUnit.SECONDS);
You may replace ScheduledExecutorService with Timer to make code clearer. And, as an option, instead of using parallel streams you can use another ExecutorService, submitting next N tasks to it on Timer and waiting until they are completed:
ExecutorService workerExecutor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
Timer timer = new Timer();
timer.schedule(new TimerTask() {
#Override
public void run() {
List<Future<Void>> futures = new ArrayList<>();
for (int i = 0; i < 50; i++) {
final int index = i;
Future<Void> future = workerExecutor.submit(new Callable<Void>() {
#Override
public Void call() throws Exception {
System.out.print(index + " ");
return null;
}
});
futures.add(future);
}
for (Future<Void> future : futures) {
try {
future.get();
} catch (InterruptedException|ExecutionException e) {
throw new RuntimeException();
}
}
System.out.println();
}
}, 0, 10_000);
....
public class mainClass {
public mainClass(){
Timer time = new Timer();
mainClass.calculate calculate = new mainClass.calculate();
time.schedule(calculate, 1 * 1000);
}
public static void main(String[] args){
new mainClass();
}
class calculate extends TimerTask{
#Override
public void run() {
System.out.println("working..");
}
}
}
I saw only one times "working.." message in the console.I want to saw every second "working.." whats the problem on code? and my another problem i want to running every second my own method but how?
Sory for my bad english..
Timer.schedule(TimerTask task, long delay) only runs the TimerTask once, after the number of milliseconds in the second argument.
To repeatedly run the TimerTask, you need to use one of the other schedule() overloads such as Timer.schedule(TimerTask task, long delay, long period), for example:
time.schedule(calculate, 1000, 1000);
which schedules the task to be executed 1000 milliseconds from now, and to repeat every 1000 milliseconds.
It is supposed to be one time according to the documentation:
public void schedule(TimerTask task,
long delay) Schedules the specified task for execution after the specified delay. Parameters: task - task to be
scheduled. delay - delay in milliseconds before task is to be
executed. Throws: IllegalArgumentException - if delay is negative, or
delay + System.currentTimeMillis() is negative. IllegalStateException
- if task was already scheduled or cancelled, or timer was cancelled.
you probably want to call
public void schedule(TimerTask task,
long delay,
long period)
You need to use:
zaman.schedule(calculate, 0, 1000);
to schedule the timer to run more than once.
You need to wait in your main thread for the timer to be fired. The JVM will exit when all the non daemon threads are completed. The thread that runs your main method is actually the only non damon thread so you should make it wait until your work is complete.
Change your main method like this:
public static void main(String[] args){
new mainClass();
Thread.sleep(2 * 1000); // wait longer than what the timer
// should wait so you can see it firing.
}
The version of Timer.schedule() which you are using only executes the task once after a delay. You need to use `Timer.schedule(TimerTask, long, long) to cause the task to repeat.
I am working on a Java EE Based application, where I need to PDF reports using itext API.
Basically my requirement is that, if the report generation takes more than 1 minute then stop it.
So for this I am implementing this business requirement in this way
Thread t = new Thread(myPojoclass);
long startTime = System.currentTimeMillis();
long endTime = startTime + 60000;
t.start();
while (System.currentTimeMillis() < endTime)
{
}
t.interrupt(); // Tell the thread to stop
And inside my myPojoclass as mentioned above, this is a Thread which implements Runnable interface and inside its run method it is consisting of connecting to Database
and getting the results and giving it to an ArrayList
Please let me know if this is correct ??
there is a good solution here. Since your thread is connecting to a database I strongly recommend (if you haven't done it already) to catch the InterruptException exception and within its block close your connection and rollback if necessary.
you can use executor service
ScheduledExecutorService executor = Executors.newScheduledThreadPool(2);
final Future handler = executor.submit(new Callable(){ ... });
executor.schedule(new Runnable(){
public void run(){
handler.cancel();
}
}, 60000, TimeUnit.MILLISECONDS);
more details
ExecutorService that interrupts tasks after a timeout
Here is the use case:
I am using Java (with Spring)
Once the user (through a web-app) confirms to the subscription, I want to send him an email exactly after 30 mins.
Now how to do this? Do I need a message broker? or something like ScheduledExecutorService?
Do I need some sort of queue?
Please advise.
Can look into quartz scheduler for this.
By the way a common strategy is to send a bulk of all pending mails in bulk in every 30 minutes or so. Quartz can help in do that as well.
You can use the Quartz Scheduler. Its fairly easy to use. You can schedule something every week or ever 30 minutes or whatever you want basically.
Create an object for Timer
private Timer myTimer;
in main method
myTimer = new Timer();
myTimer.schedule(new TimerTask() {
#Override
public void run() {
//your method
}
}, 0, 200);
It is not that the thread will die after sending the mail. When you configure Quartz, a new thread will automatically be created and will execute the assigned task on specified interval. Or else you use Timer class also. It is very easy to use.
Timer timer = new Timer(); // Get timer
long delay = 30 * 60 * 1000; // 3o min delay
// Schedule the two timers to run with different delays.
timer.schedule(new MyTask(), 0, delay);
...................
class MyTask extends TimerTask {
public void run() {
// business logic
// send mail here
}
}