package core.framework.impl.module;
import core.framework.api.util.Lists;
import core.framework.api.util.Randoms;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.time.Duration;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
/**
* @author neo
*/
public class BackgroundTaskExecutor {
private final Logger logger = LoggerFactory.getLogger(BackgroundTaskExecutor.class);
private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(new BackgroundTaskThreadFactory());
private final List<BackgroundTask> tasks = Lists.newArrayList();
public void start() {
for (BackgroundTask task : tasks) {
Duration delay = Duration.ofMillis((long) Randoms.number(8000, 15000)); // delay 8s to 15s
scheduler.scheduleWithFixedDelay(task, delay.toMillis(), task.rate.toMillis(), TimeUnit.MILLISECONDS);
}
logger.info("background task executor started");
}
public void stop() {
logger.info("stop background task executor");
scheduler.shutdown();
}
public void scheduleWithFixedDelay(Runnable command, Duration rate) {
tasks.add(new BackgroundTask(command, rate));
}
private static class BackgroundTaskThreadFactory implements ThreadFactory {
@Override
public Thread newThread(Runnable runnable) {
Thread thread = new Thread(runnable, "background-task");
thread.setPriority(Thread.NORM_PRIORITY - 1);
thread.setDaemon(true);
return thread;
}
}
private static class BackgroundTask implements Runnable {
private final Logger logger = LoggerFactory.getLogger(BackgroundTask.class);
private final Runnable command;
private final Duration rate;
BackgroundTask(Runnable command, Duration rate) {
this.command = command;
this.rate = rate;
}
@Override
public void run() {
try {
command.run();
} catch (Throwable e) {
logger.warn("failed to run background task, error=" + e.getMessage(), e);
}
}
}
}