I have a web application that synchronizes with a central database four times per hour. The process usually takes 2 minutes. I would like to run this process as a thread at X:55, X:10, X:25, and X:40 so that the users knows that at X:00, X:15, X:30, and X:45 they have a clean copy of the database. It is just about managing expectations. I have gone through the executor in java.util.concurrent but the scheduling is done with the scheduleAtFixedRate which I believe provides no guarantee about when this is actually run in terms of the hours. I could use a first delay to launch the Runnable so that the first one is close to the launch time and schedule for every 15 minutes but it seems that this would probably diverge in time. Is there an easier way to schedule the thread to run 5 minutes before every quarter hour?
You can let the Runnable schedule its "next run".
Such as,
class Task implements Runnable {
private final ScheduledExecutorService service;
public Task(ScheduledExecutorService service){
this.service = service;
}
public void run(){
try{
//do stuff
}finally{
//Prevent this task from stalling due to RuntimeExceptions.
long untilNextInvocation = //calculate how many ms to next launch
service.schedule(new Task(service),untilNextInvocation,TimeUnit.MILLISECONDS);
}
}
}
Quartz would be a good fit since you're application is web-based. It will provide the fine-grained time based scheduling you need.
Quartz is a full-featured, open source
job scheduling service that can be
integrated with, or used along side
virtually any Java EE or Java SE
application - from the smallest
stand-alone application to the largest
e-commerce system. Quartz can be used
to create simple or complex schedules
for executing tens, hundreds, or even
tens-of-thousands of jobs; jobs whose
tasks are defined as standard Java
components that may executed virtually
anything you may program them to do.
The Quartz Scheduler includes many
enterprise-class features, such as JTA
transactions and clustering.
TimerTask handles this case.
See schedule(TimerTask, Date)
If you don't want to have to keep scheduling the jobs, you may want to look into a job scheduling tool like Quartz.
Related
I am developing Java REST Web Service using Spring and Hibernate. I need to implement a feature to schedule a future task. For example, When User Sign Up in my application I have to credit him 100 virtual credits to his account for first six months. Like this there is some more similar features.
I am thinking like TimerTask can be used for this feature. The problem is If I create Timer for each users who sign up, I can't able to stop Timer of specific user if he goes inactive and it seems like dumping Thread in memory. If 1000 users sign up there will be 1000 TimerTask Threads.
How to implement this kind of feature using Spring or Java? I should have the full control over the Thread, I can able to stop thread If I want.
you can use a Single thread to perform a task with #scheduled annotation and minimal XML configuration, I'll leave the link for your reference.
you're just required to create a method in your service and place #Scheduled annotation like
#Scheduled(cron = "0 15 10 15 * ?")
public void scheduleTaskUsingCronExpression(){
long now = System.currentTimeMillis() / 1000;
System.out.println("schedule tasks using cron jobs - " + now);
}
I want a mechanism that will start a java program ( quite a big one ) depending on 2 conditions:
N new inserts in a MySQL table
Every 5 minutes interval.
I know that I can do this through crontab or using Timer or using Stored Procedure etc.
My plan is to write a Java class ( I am most familiar with ), Listener having two threads in parallel - Database Listener and Time listener threads each of them monitoring one of these conditions. If one says, yes, the parent class will start a new thread to run the Program.
I feel that it will be a heavy weight program. Is there some other option that I am overlooking at?
Write a single job. Have it execute regularly.
Effectively, you'll be doing some something of the nature of:
SELECT count(*) FROM table WHERE new = 1;
(or whatever)
Run that every second, 5 seconds, 10 seconds, whatever seems reasonable based on your activity.
When count == N, run your process. When "time since last run" == 5 minutes, run your process.
The process is the same, you just check it more often with the two criteria.
This offers an advantage that you won't get rogue race condition where the job fires TWICE (because Job A found the insert count that just-so-happens to have been 5 minutes from when the last job ran). Rare, yes, but race conditions always seem to actively seek "rare" events that "never happen".
As for scheduling, a crontab is easy because you don't have to maintain your process, keep it alive, daemonize, etc. etc.
If you're already running in a long running container (app server, tomcat, etc.) then that problem is already solved and you can just leverage that.
Downside of cron is it's granularity, it only runs at most every minute. If that too long, it won't work for you. But if it's ok, then there's real value in having a simple process that just lights up, does it's check, and quits. Of course, it will have to persist it's state somehow (it could look in a job log to see when the last job ran, for example).
Within java, there are lots of options: raw threads, sleeping, Timers, ScheduledExecutorService, something like Quartz, EJB Timer beans (if you're running a Java EE container).
But, I'm a KISS fan. If a cron job can do it, let it, and do it once.
It is actually not that big using a ScheduledExecutorService:
private static final Runnable PROGRAM_RUNNABLE = new Runnable() {
#Override
public void run() {
// run the program
}
}
private ScheduledExecutorService ses = Executors.newScheduledThreadPool(2);
public static void main(String[] args) {
// database based
ses.scheduleAtFixedRate(new Runnable() {
#Override
public void run() {
boolean inserted = checkDatabase(); // check the insert in the db
if(inserted) {
PROGRAM_RUNNABLE.run();
}
}
}, 0, 1, TimeUnit.MINUTES);
// time based
ses.scheduleAtFixedRate(PROGRAM_RUNNABLE, 5, 5, TimeUnit.MINUTES);
}
I have run into a case where I have to use a persistent Scheduler, since I have a web application that can crash or close due to some problems and might lose it job details if this happens . I have tried the following:
Use Quartz scheduler:
I used RAMJobStore first, but since it isn't persistent, it wasn't of much help. Can't setup JDBCJobStore because, this will require huge code changes to my existing code base.
In light of such a scenario,
I have the following queries:
If I use Spring's built in #Schedule annotation will my jobs be persistent..? I don't mind if the jobs get scheduled after the application starts. All I want is the jobs to not lose their details and triggers.?
If not, are there any other alternatives that can be followed , keeping in mind that I need to schedule multiple jobs with my scheduler.?
If yes, how can I achieve this.? My triggers are different each job. For e.g I might have a job that is scheduled at 9AM and another at 8.30AM and so on.
If not a scheduler, then can I have a mechanism to handle this.?
One thing, I found is that the documentation for Quartz isn't very descriptive. I mean it's fine for a top level config, but configuring it on your an application is a pain. This is just a side note. Nothing to do with the question.
Appreciate the help. :)
No, Spring's #Schedule-annotation will typically only instruct Spring at what times a certain task should be scheduled to run within the current VM. As far as I know there is not a context for the execution either. The schedule is static.
I had a similar requirement and created db-scheduler (https://github.com/kagkarlsson/db-scheduler), a simple, persistent and cluster-friendly scheduler. It stores the next execution-time in the database, and triggers execution once it is reached.
A very simple example for a RecurringTask without context could look like this:
final RecurringTask myDailyTask = ComposableTask.recurringTask("my-daily-task", Schedules.daily(LocalTime.of(8, 0)),
() -> System.out.println("Executed!"));
final Scheduler scheduler = Scheduler
.create(dataSource)
.startTasks(myDailyTask)
.threads(5)
.build();
scheduler.start();
It will execute the task named my-daily-task at 08:00 every day. It will be scheduled in the database when the scheduler is first started, unless it already exists in the database.
If you want to schedule an ad-hoc task some time in the future with context, you can use the OneTimeTask:
final OneTimeTask oneTimeTask = ComposableTask.onetimeTask("my-onetime-task",
(taskInstance, context) -> System.out.println("One-time task with identifier "+taskInstance.getId()+" executed!"));
scheduler.scheduleForExecution(LocalDateTime.now().plusDays(1), oneTimeTask.instance("1001"));
See the example above. Any number of tasks can be scheduled, as long as task-name and instanceIdentifier is unique.
#Schedule has nothing to do with the actual executor. The default java executors aren't persistent (maybe there are some app-server specific ones that are), if you want persistence you have to use Quartz for job execution.
All,
What is a really simple way of having a program do more than one thing at once, even if the computer does not necessarily have multiple 'cores'. Can I do this by creating more than one Thread?
My goal is to be able to have two computers networked (through Sockets) to respond to each-other's requests, while my program will at the same time be able to be managing a UI. I want the server to potentially handle more than one client at the same time as well.
My understanding is that the communication is done with BufferedReader.readLine() and PrintWriter.println(). My problem is that I want the server to be waiting on multiple readLine() requests, and also be doing other things. How do I handle this?
Many thanks,
Jonathan
Yes, you can do this by having multiple threads inside your Java program.
As the mechanisms in Java gets rather complicated when you do this, have a look at the appropriate section in the Java Tutorial:
http://java.sun.com/docs/books/tutorial/essential/concurrency/
Yes, just create multiple threads. They will run concurrently, whether or not the processor has multiple cores. (With a single core, the OS simply suspends the execution of the running thread at certain points and runs another thread for a while, so in effect, multiple ones seem to be running at the same time).
Here's a good concurrency tutorial: http://java.sun.com/docs/books/tutorial/essential/concurrency/
The standard Java tutorial for Sockets is a good start. I wrote the exact program you are describing using this as a base. The last point on the page "Supporting Multiple Clients" describes how threads are implemented.
http://java.sun.com/docs/books/tutorial/networking/sockets/clientServer.html
Have a look at this page: http://www.ashishmyles.com/tutorials/tcpchat/index.html -- it gives a good description of threads, UI details, etc, and gives a chat example where they merge the two together.
Also, consider using Apache MINA. It's quite lightweight, doesn't rely on any external libraries (apart from slf4j) and makes it very easy to get stuff from sockets without needing to go around in as loop, and it's also quite non-blocking (or blocking when you need it to be). So, you have a class which implements IoHandler and then you register that with an acceptor or some other Mina connection class. Then, it notifies you about when packets are received. It handles all the usually-crippling backend stuff for you in a pleasant way (i.e., manually creating multiple threads for clients and then managing these).
It also has codec support, where you can transform sent and received messages. So, say you want to receive Java objects on either end of your connection -- this will do the conversion for you. Perhaps you also want to zip them up to make it more efficient? You can write that too, adding that to the chain below the object codec.
Can I do this by creating more than one Thread?
What is a really simple way of having
a program do more than one thing at
once, even if the computer does not
necessarily have multiple 'cores'. Can
I do this by creating more than one
Thread?
If you have 1 single core, then "official" only 1 task can be executed at the same time. Because your computer
s processor is so fast and executes so many instructions per second it creates the illusion that your computer is doing multiple tasks simultaneously while every small unit it only executes 1 task. You can create this illusion in Java by creating threads which get scheduled by your operating system to run for a short period of time.
My advice is to have a look at the java.util.concurrent package because it contains a lot of helpful tools to make playing around with threads a lot easier(Back in the days when this package did not exists it was a lot harder). I for example like to use
ExecutorService es = Executors.newCachedThreadPool();
to create a thread pool which I can submit tasks to run simultaneously. Then when I have task which I like to have run, I call
es.execute(runnable);
where runnable looks like:
Runnable runnable = new Runnable() {
public void run() {
// code to run.
}
};
For example say you run the following code:
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package mytests;
import java.util.Date;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
*
* #author alfred
*/
public class Main {
/**
* #param args the command line arguments
* #throws Exception
*/
public static void main(String[] args) throws Exception {
// TODO code application logic here
final CountDownLatch latch = new CountDownLatch(2);
final long start = System.nanoTime();
ExecutorService es = Executors.newCachedThreadPool();
Runnable runnable = new Runnable() {
public void run() {
sleep(1);
System.out.println(new Date());
latch.countDown();
}
};
es.submit(runnable);
es.submit(runnable);
latch.await(); // waits only latch.countDown() has been called 2 times.
// 1 nanoseconds is equal to 1/1000000000 of a second.
long total = (System.nanoTime() - start) / 1000000;
System.out.println("total time: " + total);
es.shutdown();
}
public static void sleep(int i) {
try {
Thread.sleep(i * 1000);
} catch (InterruptedException ie) {}
}
}
The output would look like
run:
Fri Apr 02 03:34:14 CEST 2010
Fri Apr 02 03:34:14 CEST 2010
total time: 1055
BUILD SUCCESSFUL (total time: 1 second)
But I ran 2 tasks which each both ran for at least 1 second(because of sleep of 1 second). If I would run those 2 tasks sequentially then it would take at least 2 seconds, but because I used threads it only took 1 second. This is what you wanted and it is easily accomplished using the java.util.concurrent package.
I want the server to potentially handle more than one client at the same time as well.
My goal is to be able to have two
computers networked (through Sockets)
to respond to each-other's requests,
while my program will at the same time
be able to be managing a UI. I want
the server to potentially handle more
than one client at the same time as
well.
I would advice you to have a look at Netty framework(MINA which also developed by the creator of MINA, but Netty is better(more development) in my opinion).:
The Netty project is an effort to
provide an asynchronous event-driven
network application framework and
tools for rapid development of
maintainable high performance & high
scalability protocol servers &
clients.
It will do all the heavy lifting for you. When I read the user guide I was totally amazed with netty. Netty uses nio which is for highly concurrent servers the new way to do IO which scales much better. Like I said before this framework does all the heavy lifting for you
My problem is that I want the server to be waiting on multiple readLine() requests, and also be doing other things
My understanding is that the
communication is done with
BufferedReader.readLine() and
PrintWriter.println(). My problem is
that I want the server to be waiting
on multiple readLine() requests, and
also be doing other things. How do I
handle this?
Again when you look into the netty's user guide + examples you will find out that it does all the heavy lifting for you in an efficient way. You will only have to specify some simple callbacks to get the data from the clients.
Hopefully this has answered all your question. Else I would advice you to leave a comment so that I will try to explain it better.
I have an application that runs in JBoss. I have an incoming web service request that will update an ArrayList. I want to poll this list from another class every 60 seconds. What would be the most efficient way of doing this?
Could anyone point me to a good example?
I would also recommend ScheduledExecutorService, which offers increased flexibility over Timer and TimerTask including the ability to configure the service with multiple threads. This means that if a specific task takes a long time to run it will not prevent other tasks from commencing.
// Create a service with 3 threads.
ScheduledExecutorService execService = Executors.newScheduledThreadPool(3);
// Schedule a task to run every 5 seconds with no initial delay.
execService.scheduleAtFixedRate(new Runnable() {
public void run() {
System.err.println("Hello, World");
}
}, 0L, 5L, TimeUnit.SECONDS);
As abyx posted, Timer and TimerTask are a good lightweight solution to running a class at a certain interval. If you need a heavy duty scheduler, may I suggest Quartz. It is an enterprise level job scheduler. It can easily handle thousands of scheduled jobs. Like I said, this might be overkill for your situation though.
You can use Timer and TimerTask. An example is shown here.
See java.util.Timer. You'll need to start a robot in a separate thread when your app comes up and have it do the polling.
Check the answers to the question "How to run a task daily from Java" for a list of resources related to your problem.
The other answers are basically advising you do your own threads. Nothing wrong with that, but it isn't in conformance with the EJB spec. If that is a problem, you can use JBoss' timer facilities. Here is an example of how to do that.
However, if the EJB spec is at issue, storing state like an ArrayList isn't compliant as well, so if you are just reading some static variable anyway, specifically using a container Timer service is likely overkill.