implement a scheduler in spring - java

A project requires the following scenario to happen:
class A has some objects(dynamically created) which it generates along with a time interval associated with each object. This class needs the generated object after this time interval only. I need to implement a mechanism which provides the class with the objects after it's associated time interval. It may also, sometime, need a particular object before the time interval expires.
Here's what I did:
Looked upon ConcurrentTaskExecutor and org.springframework.scheduling.concurrent but didn't find it useful because I don't want thousands of thread running each for an object. Also, I don't want to repeat a particular job after a time interval.
I created a Thread B which takes all the object in a queue, has an infinite loop which constantly checks all the object's time interval with the current time, and puts back if it's time interval has not expired.
while (true) {
timerObject = queue.take();
if (timerObject.getEndTime() < System.currentTimeMillis()) {
//Do something
} else {
queue.put(timerObject);
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
This is not a very efficient implementation itself. It has a logical error associated with it. When the objects are very low in number(like 1 or 2), the objects are not in the queue and whenever I try to remove the object from the queue, it shows unsuccessful, because the while loop is having the object all the time. And hence I had to put a sleep to avoid that. I don't want to check each and every time interval when the queue size grows up to 10K or so.
Is there any simple and efficient way to achieve the solution. Any help appreciated.

You can use ConcurrentTaskScheduler, or implement something like it using DelayQueue.
You can use it with spring's Concurrent framework (for example subclassing ThreadPoolExecutorFactoryBean) or with core java Executors.

Related

Push notifications using Spring Boot

I hope you can advise me.
I have a Spring Boot API and a mobile app. I have to send push notifications to the users one hour before they have to do something, like a reminder. I have the specific date and time stored in a database.
I've been reading about scheduled tasks but I don't like it at all.
So, what do you think is the best way to do this?
I've been reading about scheduled tasks but I don't like it at all.
How else should it work? You need some kind of Scheduler / Timer that triggers your code at the specified time.
You could go for the simplest solution that came to my mind:
long delay = ...; // calculate the delay when the code should be executed
Runnable theCodeToExecute = () -> System.out.println("hello world");
new Thread(() -> {
try {
Thread.sleep(delay);
runnable.run();
}
catch (Exception e){
System.err.println(e);
}
}).start();
This of course has several disadvantages: When you restart your app, the scheduled task is gone. And it won't be very efficient when you have hundreds of threads sleeping.
There are of course ways to circumvent this:
Store your timers in a database (or in a file). And remove the entries when you sent the notification. And when your application restarts, you simply read the stored entries and restart the timers.
You could use a Queue (or sorted List) of tasks. And have a single Thread, that looks every N seconds for the next task in the queue. If this task is ready, remove it from the Queue (or List) and execute the code.
As an alternative, you can of course use a Framework that already does all of this for you, like for example Quartz

How to timeout current running API call without using any extra threads?

I have been looking for answer to this from one week, couldn't find anything relatable. Finally decided to post here.
I have use-case, where I need to give custom timeouts to different API calls. This use-case sounds very common. right ? well, I want to achieve this without using any extra threads. I am looking for system-clock described as given below.
So basically, I want to write one method ( calling it, EnforceTimeout() ), This method takes callable ( API call converted into callable format, which returns response, or exception ), and timeout in Miliseconds.
public static Object EnforceTimeout(Callable callable, Long TimeoutInMS) throws exceptions {
// Do Some Steps on current thread, but not create new thread/thread-pool
// 1. Start the clock
// 2. Make API call
// 3. Clock runs in background which takes care of the timeout, and if API call exceeds the time-limit then automatically enforce the exception.
}
Now, Some of you might have doubt, how can we keep track of elapsed time, without creating new thread. So here, let me describe a strategy like an Event-loop( in JavaScript ). We can define a system-clock. This clock should be able to look after 10 to 100 such callable's timeouts. It can check on such callable on priority queue (whichever callable has closest ending time), whether we have crossed the time limit.
Your next argument would be, one such system-clock instance would be inefficient to manage large number of callables. In that case, We need system-clock-manager, which will manage, how many such a clocks we will need, it should be able to handle the scaling of such system clock instances.
Please, let me know, if anything as such possible in java. If my question/idea is duplicate, pls guide me to the discussion, where I can find more information about the same. Thank you very much.

Jira: Thread-safe Gadget Data?

I have some data (two HashSets and a timestamp Instant) that I'd like all requests to my JIRA (OpenSocial?) gadget/plugin to share -- because it takes a long time to generate (couple of minutes) and because the sharing will help the requests be more performant.
Occasionally (very rarely), a request might include a parameter that indicates this shared data should be refreshed. And of course the first time it's needed, it gets populated. It is okay for the data to represent a stale answer -- it is based on things that change slowly and used to visualize trends so off-by-one errors are tolerable.
I imagine when JIRA starts up (or I upload a new version of my add-on) and multiple requests come in during the first couple of minutes, I'd need to handle the population of this expensive shared data in a thread-safe way. Currently the results look fine but as I understand it, that's been just due to chance.
Only one thread needs to do the work of populating. On start-up, the other threads will have to wait of course because they can't skip ahead empty-handed. (If all threads do the expensive initialization, that's a lot of unnecessary load on the server)
But after the initial cost, if multiple concurrent requests come in and one of them includes the 'refresh' parameter, only that one thread needs to pay the price -- I'm fine with the other threads using an old copy of the expensive data and thereby staying performant, and including in the response that "yes someone out there is refreshing the data but here's a result using an old copy".
More about the data: The two HashSets and the timestamp are intended to represent a consistent snapshot in time. The HashSet contents depend on values in the database only, and the timestamp is just the time of the most recent refresh. None of this data depends on any earlier snapshot in time. And none of it depends on program state either. The timestamp is only used to answer the question "how old is this data" in a rough sense. Every time the data is refreshed, I'd expect the timestamp to be more recent but nothing is going to break if it's wrong. It's just for debugging and transparency. Since a snapshot doesn't depend on earlier snapshots or the program state, it could be wrapped and marked as volatile.
Is there an obvious choice for the best way to go about this? Pros and cons of alternatives?
You'll want to use Locks to synchronize access to the sections of your code that you need to have only one thread executing at once. There are plenty of resources on SO and in the Oracle Java docs that show how to use locks in more detail, but something like this should do the trick.
The idea is that you want to maintain a copy of the most-recently generated set of results, and you always return that copy until you have a new set of data available.
import java.util.concurrent.locks.ReentrantLock;
public class MyClass
{
private volatile MyObject completedResults;
private final ReentrantLock resultsLock;
private final ReentrantLock refreshLock;
public MyClass()
{
// This must be a singleton class (such as a servlet) for this to work, since every
// thread needs to be accessing the same lock.
resultsLock = new ReentrantLock();
refreshLock = new ReentrantLock();
}
public MyObject myMethodToRequestResults(boolean refresh)
{
MyObject resultsToReturn;
// Serialize access to get the most-recently completed set of results; if none exists,
// we need to generate it and all requesting threads need to wait.
resultsLock.lock();
try
{
if (completedResults == null)
{
completedResults = generateResults();
refresh = false; // we just generated it, so no point in redoing it below
}
resultsToReturn = completedResults;
}
finally
{
resultsLock.unlock();
}
if (refresh)
{
// If someone else is regenerating, we just return the old data and tell the caller that.
if (!refreshLock.tryLock())
{
// create a copy of the results to return, since we're about to modify it on the next line
// and we don't want to change the (shared) original!
resultsToReturn = new MyObject(resultsToReturn);
resultsToReturn.setSomeoneElseIsRegeneratingTheStuffRightNow(true);
}
else
{
try
{
completedResults = generateResults();
resultsToReturn = completedResults;
}
finally
{
refreshLock.unlock();
}
}
}
return resultsToReturn;
}
}

constantly check database [duplicate]

I'm using JDBC, need to constantly check the database against changing values.
What I have currently is an infinite loop running, inner loop iterating over a changing values, and each iteration checking against the database.
public void runInBG() { //this method called from another thread
while(true) {
while(els.hasElements()) {
Test el = (Test)els.next();
String sql = "SELECT * FROM Test WHERE id = '" + el.getId() + "'";
Record r = db.getTestRecord(sql);//this function makes connection, executeQuery etc...and return Record object with values
if(r != null) {
//do something
}
}
}
}
I'm think this isn't the best way.
The other way I'm thinking is the reverse, to keep iterating over the database.
UPDATE
Thank you for the feedback regarding timers, but I don't think it will solve my problem.
Once a change occurs in the database I need to process the results almost instantaneously against the changing values ("els" from the example code).
Even if the database does not change it still has to check constantly against the changing values.
UPDATE 2
OK, to anyone interested in the answer I believe I have the solution now. Basically the solution is NOT to use the database for this. Load in, update, add, etc... only whats needed from the database to memory.
That way you don't have to open and close the database constantly, you only deal with the database when you make a change to it, and reflect those changes back into memory and only deal with whatever is in memory at the time.
Sure this is more memory intensive but performance is absolute key here.
As to the periodic "timer" answers, I'm sorry but this is not right at all. Nobody has responded with a reason how the use of timers would solve this particular situation.
But thank you again for the feedback, it was still helpful nevertheless.
Another possibility would be using ScheduledThreadPoolExecutor.
You could implement a Runnable containing your logic and register it to the ScheduledExecutorService as follows:
ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(10);
executor.scheduleAtFixedRate(myRunnable, 0, 5, TimeUnit.SECONDS);
The code above, creates a ScheduledThreadPoolExecutor with 10 Threads in its pool, and would have a Runnable registered to it that will run in a 5 seconds period starting immediately.
To schedule your runnable you could use:
scheduleAtFixedRate
Creates and executes a periodic action that becomes enabled first after the given initial delay, and subsequently with the given period; that is executions will commence after initialDelay then initialDelay+period, then initialDelay + 2 * period, and so on.
scheduleWithFixedDelay
Creates and executes a periodic action that becomes enabled first after the given initial delay, and subsequently with the given delay between the termination of one execution and the commencement of the next.
And here you can see the advantages of ThreadPoolExecutor, in order to see if it fits to your requirements. I advise this question: Java Timer vs ExecutorService? too in order to make a good decision.
Keeping the while(true) in the runInBG() is a bad idea. You better remove that. Instead you can have a Scheduler/Timer(use Timer & TimerTask) which would call the runInBG() periodically and check for the updates in the DB.
u could use a timer--->
Timer timer = new Timer("runInBG");
//Taking an instance of class contains your repeated method.
MyClass t = new MyClass();
timer.schedule(t, 0, 2000);
As you said in the comment above, if application controls the updates and inserts then you can create a framework which notifies for 'BG' thread or process about change in database. Notification can be over network via JMS or intra VM using observer pattern or both local and remote notifications.
You can have generic notification message like (it can be class for local notification or text message for remote notifications)
<Notification>
<Type>update/insert</Type>
<Entity>
<Name>Account/Customer</Name>
<Id>id</Id>
<Entity>
</Notification>
To avoid a 'busy loop', I would try to use triggers. H2 also supports a DatabaseEventListener API, that way you wouldn't have to create a trigger for each table.
This may not always work, for example if you use a remote connection.
UPDATE 2
OK, to anyone interested in the answer I believe I have the solution now. Basically the solution is NOT to use the database for this. Load in, update, add, etc... only whats needed from the database to memory. That way you don't have to open and close the database constantly, you only deal with the database when you make a change to it, and reflect those changes back into memory and only deal with whatever is in memory at the time. Sure this is more memory intensive but performance is absolute key here.

Waiting before returning within Java

Right now, I have a piece of code that contacts another server asking if an item is in a list, and returns a boolean value based on that returned value.
The code goes like so:
public boolean checkIfOnline(int accountId) {
//First loop is incase if someone is already checking. Second is for the checking that this account is doing.
while (isCheckingIfOnline) {
try {
Thread.sleep(1);
} catch (InterruptedException ex) {
}
}
isCheckingIfOnline = true;
sendCheckIfOnline(accountId);
while (isCheckingIfOnline) {
try {
Thread.sleep(1);
} catch (InterruptedException ex) {
}
}
return onlineResponse;
}
The onlineResponse and isCheckingIfOnline are changed within a method that handles what the other server returns, and this is the method I've thrown together to have the system wait for the other server to respond. Obviously, this is very flawed, as when this method gets called often, it'll slow down the system since it only allows for one query at a time, when it should allow for multiple queries to be executed simultaneously.
What other method could I use that accomplishes what the above code does, but allows for more than one query to run at once?
Edit: To clarify even more, checkIfOnline takes an account ID, and asks another server is that account ID is on a list, which that other server responds to the current server if the account ID is or is not on the list.
Sounds like you would want to make use of the ExecutorService in Java 6+.
The ExecutorService requires you to submit to it a class that implements Callable. When you submit a Callable to a ES, you receive back a Future that you can use to do a number of things, including cancelling the process or getting a result from a completed process.
It's a little hard for me to understand exactly what you are trying to achieve with your code and why you're threading that particular part. That being said, if you want to achieve concurrency there, you'd have to:
submit a Callable to the ES that does the online checks & query;
provide a way for the Callable to notify the your application that it has finished it's execution.
It will not be sufficient to simply submit the task and call Future.get() on it because whatever thread makes that call will be suspended until the task is completed.
You'd need to either allow the Callable to invoke a callback, or thread the class that performs the submission of the task and allow it to sit and wait for the future.get() method to return a result.
Good luck :)

Categories

Resources