java threading issue, right approach? - java

I am creating a java service which will continuously run in the background and the job of the service is to create a copy of the table at a particular date. To be exact, i read data from some table and if record_date in table matches the current date, i need to create the table copy. Then the service should sleep until the next date to run. Next date to run is also determined by looking at the record in the table.
Currently, how i do this, is to create a thread which runs in while(true) loop. and when thread is finished performing the task i.e. creating a table copy, I put it to sleep using Thread.sleep() until next time it needs to run. The number of milliseconds for thread to sleep, i calculate by taking the difference between the current date (date on which the task is performed by thread) and the next run date.
Is this the right approach, is using thread.sleep() for this particular scenario the right thing? I say this because next run date for a thread could be after three months or even a year. Also please let me know if i am not very clear here.

What about dissecting both operations?
Write a Java Job which when invokes checks for date in the table and create a copy.
Schedule the java job to run the way you want it to run.
Since we UNIX so cron helps us a lot in doing such tasks.

Have a look at the Lock interface. This is an abstraction for wait() and notify(), which is what you should use instead of sleep().
There is an answer here which illustrates why.

Check out the Java Timer API or the Quartz library

Related

Java time based execution

I want to do the following. I count the occurence of an event in my program. What I wish to achieve is that at the end of every hour (Of the MST i.e the time zone where I am in) the count be recorded in the database for that hour. All I need is a code snippet which would execute at the end of every hour. Note that I don't want the thread to sleep because I also need to update counts when events occur.
You can implement a TimerTask so search for that. Or if you can use Quartz. Google search should be your first stop.
In Java, there's no way to ensure that a Runnable gets executed exactly at a given time.
You can only schedule a Runnable to be executed at intervals of approximately a given time. If that's enough for you, then a java.util.Timer or Executors.newSingleThreadScheduledExecutor() is good enough. You only need to put your counter in a thread-safe and atomic variable (AtomicInteger may be enough, depending on the numbers you are expecting to have).
If you want to have extreme precision, then you'd better modify your event handler, so that, before recording the event, it checks in which hour it is and, depending on that, it uses a different "slot" inside a queue. Finally, your scheduled task would gather old queue slots, removing them from the queue and storing to database. (I think this is excessive, but it's up to you).

Which java concurrent to use for cleaning DB (on demand/scheduled)

I have a thread cleaner in my code that is being created if the DB capacity was exceeded, the capacity is checked on every insertion to the DB. I would like to add more functionality to this cleaner and clean also when number of files exceeding, lets say 10000 files. The new functionality should run scheduled.
I want to be able to clean the DB in 2 ways:
1. On demand.
2. Scheduled, every day on X hour.
Which concurrent java class to use?
How can I make sure that the same thread will be used by the 2 ways above?
Code that would perform cleanup of DB should be completely separated out of scheduling (single responsibility principle), so that you could execute it at any time from some other code.
As for scheduling, I would suggest you looking at Quartz scheduler, and get familiar with CRON so that you could extract it to properties to have possibility to change scheduling trigger without modifying your code.
You should synchronize your code so that no more than one cleanup gets performed at the same time, this should be easy with standard synchronize.
If you wish to make it very simple and don't want to add new dependencies, you can go with standard Java solution: Timer. Timer#scheduleAtFixedRate can provide fixed rate execution. Which means you'll have to add extra code whenever new requirements will show up (e.g., don't schedule at weekend).

How do you set an ETA for a task in GAE's task engine?

I'm trying to run a task an hour in the future. Here's what I'm doing, doesn't seem to work.
import static com.google.appengine.api.taskqueue.TaskOptions.Builder.*;
Calendar cal = Calendar.getInstance();
cal.setTime(new Date());
cal.add(Calendar.HOUR, 1);
cal.getTime();
Queue queue = QueueFactory.getDefaultQueue();
queue.add(withUrl("/task/doMyThing").param("userId", userId).header("X-AppEngine-TaskETA", cal.getTime().getTime()+""));
-edit
OK then a little more clarification: When someone hits my service I want to call a Java method exactly an hour after they hit the service. I assumed the task queue was the best way to do that on App Engine. I thought the queue would not execute that task unless the ETA had passed. If I'm approaching this the wrong way and there's a better way to accomplish it please let me know.
-edit again
Thanks for the answers, for the record here's what I did:
Queue queue = QueueFactory.getDefaultQueue();
queue.add(withUrl("/task/sendReminder").param("userId", userId).countdownMillis(120000));
I've done what you're trying to do but in python. I think the header you're trying to set is one that appengine sets when it starts a task from the queue and not necessarily one that you set when you're creating the task. I think you're looking for countdownMillis with a value of 3600000.
The java
Timer Class is the one to investigate.
If you want to execute the task after an hour but as you mentioned "task an hour in the future" seems unclear
I'd take a look at DelayQueue. I'd have one thread pull objects from the DelayQueue continuously and hand them off to a cached thread pool to execute them as soon as possible, rather than use a Timer.
DelayQueue will block until the waiting period for the next item has expired. You can control when the objects can be removed from the queue by setting their delay period prior to adding them to the queue to ensure they stay in the queue for the alotted time.
Using a cached thread pool will ensure that each task gets executed as soon as it comes off the queue as well as minimize initialization time/space by reusing threads instead of initializing new ones every time a task gets pulled off the queue.

Use cron or a java loop with a sleeping process

I am trying to find the better way to update my database.
I have two solution but I don't know which is the less demanding.
The first one is to create a java program with a Thread.sleep and an infinite loop.
The second way is always with a java program but no thread sleep and infinite loop, just the update program and I execute this program using cron.
Thanks for your help
"No thread sleep" + cron is simpler and easier to maintain:
Your program does just one main thing - updates the database.
Scheduling is delegated to cron. You are more flexible in configuration and do not need to write extra code to support "scheduling"

Threads/backend in appengine java

I want to run some kind of Thread continuously in app engine. What the thread does is
checks a hashmap and updates entries as per some business continuously.
My hashmap is a public memeber variable of class X. And X is a singleton class.
Now I know that appengine do not support Thread and it has somethinking called backend.
Now my question is: If I run backend continiously for 24*7 will I be charged?
There is no heavy processing in backend. It just updates a hashmap based on some condition.
Can I apply some trick so that am not charged? My webapp is not for commercial use and is for fun.
Yes, backends are billed per hour. It does not matter how much they are used: https://developers.google.com/appengine/docs/billing#Billable_Resource_Unit_Costs
Do you need this calculation to happen immediatelly? You could run a cron job, say ever 5 min and perform the task.
Or you can too enqueue a 10 minutes task and re-enqueue when is near to arrive to its 10 minutes limit time. For that you can use the task parameters to pass the state of the process to the next task or also you can use datastore.

Categories