tech.ytsaurus.client.misc.SerializedExecutorService Maven / Gradle / Ivy
The newest version!
package tech.ytsaurus.client.misc;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.annotation.Nonnull;
/**
* An executor than ensurers serial execution of submitted tasks
* i.e. no two tasks submitted to it will be executed simultaneously.
*/
public class SerializedExecutorService implements ExecutorService {
private final ExecutorService underlying;
private final AtomicBoolean lock = new AtomicBoolean();
private final ConcurrentLinkedQueue taskQueue = new ConcurrentLinkedQueue<>();
public SerializedExecutorService(@Nonnull ExecutorService underlying) {
this.underlying = underlying;
}
@Override
public void shutdown() {
underlying.shutdown();
}
@Nonnull
@Override
public List shutdownNow() {
List result = underlying.shutdownNow();
result.addAll(taskQueue);
return result;
}
@Override
public boolean isShutdown() {
return underlying.isShutdown();
}
@Override
public boolean isTerminated() {
return underlying.isTerminated();
}
@Override
public boolean awaitTermination(long l, @Nonnull TimeUnit timeUnit) throws InterruptedException {
return underlying.awaitTermination(l, timeUnit);
}
@Nonnull
@Override
public CompletableFuture submit(@Nonnull Callable callable) {
CompletableFuture result = new CompletableFuture<>();
execute(() -> {
if (!result.isDone()) {
try {
result.complete(callable.call());
} catch (Throwable exception) {
result.completeExceptionally(exception);
}
}
});
return result;
}
@Nonnull
@Override
public CompletableFuture submit(@Nonnull Runnable runnable, T t) {
return submit(() -> {
runnable.run();
return t;
});
}
@Nonnull
@Override
public CompletableFuture submit(@Nonnull Runnable runnable) {
return submit(() -> {
runnable.run();
return null;
});
}
@Nonnull
@Override
public List> invokeAll(@Nonnull Collection extends Callable> collection) {
throw new RuntimeException("Not implemented yet");
}
@Nonnull
@Override
public List> invokeAll(
@Nonnull Collection extends Callable> collection,
long l,
@Nonnull TimeUnit timeUnit
) {
throw new RuntimeException("Not implemented yet");
}
@Nonnull
@Override
public T invokeAny(@Nonnull Collection extends Callable> collection) {
throw new RuntimeException("Not implemented yet");
}
@Override
public T invokeAny(@Nonnull Collection extends Callable> collection, long l, @Nonnull TimeUnit timeUnit) {
throw new RuntimeException("Not implemented yet");
}
@Override
public void execute(@Nonnull Runnable runnable) {
taskQueue.add(runnable);
trySchedule();
}
private void trySchedule() {
if (lock.compareAndSet(false, true)) {
underlying.execute(() -> {
Runnable r = taskQueue.poll();
if (r != null) {
r.run();
}
lock.set(false);
if (!taskQueue.isEmpty()) {
trySchedule();
}
});
}
}
}