Since there would be no work for the @Scheduled method if there are no elements in the work queue, that is, if no one puts any work on the queue between execution cycles. In the same note, if any work item was inserted into the work queue (possibly by an external source) immediately after completion of the scheduled execution, the work will not be displayed until the next execution.
In this scenario, you need a consumer queue maker. A queue in which one or more manufacturers are placed in work items, and the consumer takes items from the queue and processes them. Here you want a BlockingQueue . They can be used to solve the consumer-producer problem in a thread-safe manner.
You may have one Runnable that performs the tasks performed by your current @Scheduled method.
public class SomeClass { private final BlockingQueue<Work> workQueue = new LinkedBlockingQueue<Work>(); public BlockingQueue<Work> getWorkQueue() { return workQueue; } private final class WorkExecutor implements Runnable { @Override public void run() { while (true) { try {
And some other Runnable or another class can put elements like this:
public class WorkCreator { @Autowired private SomeClass workerClass; @Override public void run() {
I guess the right way to solve the problem is at your fingertips. There are several options / configurations you may have, just look at java.util.concurrent .
Update after question edited
Even if the external source is db, it is still a producer-consumer problem. You can probably call the scan() method whenever you store data in db, and the scan() method can put the data extracted from db into a BlockingQueue .
To address the actual issue of restarting fixedDelay
Actually this is not possible, either start Java or with Spring , if you yourself do not handle the planning part. There are no trigger-now functions. If you have access to Runnable , which performs this task, you can probably call the run() method yourself. But that would be the same as calling a processing method from anywhere, and you really don't need Runnable .
Another possible workaround
private Lock queueLock = new ReentrantLock(); @Scheduled public void findNewWorkAndProcess() { if(!queueLock.tryLock()) { return; } try { doWork(); } finally { queueLock.unlock(); } } void doWork() { List<Work> work = getWorkFromDb();
newDataInserted() is called when any new data is inserted. If the scheduled execution is in progress, it will wait until it is completed, and then do the work. The lock() call is blocked here, since we know that there is some work in the database, and the scheduled call could be called before the work has been inserted. The call to lock in findNewWorkAndProcess() when non-blocking as, if the lock was obtained by the newDataInserted method, this means that the scheduled method should not be executed.
Well, you can customize as you wish.