I'm attempting to write java code that executes a load operation as described below.
Initial Call (Thread One): Initiates a loading process and immediately returns.
Second Call (Thread Two):
If Thread One is in the midst of loading, it waits. Once Thread One finishes, Thread Two starts its own load. After its load is done, it returns.
Subsequent Calls (Thread Three and beyond): If Thread One is loading, it waits. Does not queue behind both Thread One and Thread Two. Instead, it leverages the load process initiated by Thread Two. Returns in tandem with Thread Two once the loading is completed.
The load method is called from an api-controller method.
My current implementation is not good because the same thread is handling the flush for the next threads, while it should have returned. If the method is invoked multiple times and the isLoadPending flag is set, the same thread continually handles the load, potentially without ever releasing. Ideally, after waiting for a prior load to finish, a thread should only need to flush at most one more time.
private final ReentrantLock loadLock = new ReentrantLock();
private final AtomicBoolean isLoadPending = new AtomicBoolean(false);
public void loadAll() {
if (loadLock.tryLock()) {
try {
DbLoadService.load();
while (isLoadPending.compareAndSet(true, false)) {
DbLoadService.load();
}
} finally {
loadLock.unlock();
}
} else {
isLoadPending.set(true);
loadLock.lock();
loadLock.unlock();
}
}
Any suggestions?
I think, you want something like this:
In this specific use case, the threads belonging to a particular phase are the threads entering
loadAll()
at the same time or while a previousDbLoadService.load()
is in progress. Since this is different for each phase, they have to register and unregister each time.All threads calling
register()
while a previousDbLoadService.load()
is in progress will wait for its completion, then all of them will callarriveAndDeregister()
and the last one will perform the newDbLoadService.load()
operation. The others will wait for the completion of this newDbLoadService.load()
operation inawaitAdvance
.New threads arriving at
register()
are clearly distinct from the threads waiting atawaitAdvance
at the same time—they belong to a different phase. In fact, when this overlapping happens, it is impossible for the thread performing the currentload()
to become part of the next phase, so it’s impossible for a thread to get stuck in repeatedly performing theload
operation.