io.github.icodegarden.commons.lang.schedule.AbstractSchedule Maven / Gradle / Ivy
package io.github.icodegarden.commons.lang.schedule;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import org.springframework.util.Assert;
import io.github.icodegarden.commons.lang.util.CronUtils;
import io.github.icodegarden.commons.lang.util.ThreadPoolUtils;
import lombok.extern.slf4j.Slf4j;
/**
*
* @author Fangfang.Xu
*
*/
@Slf4j
public abstract class AbstractSchedule implements Schedule {
private final ScheduledThreadPoolExecutor scheduleThreadPool = ThreadPoolUtils
.newSingleScheduledThreadPool(AbstractSchedule.this.getClass().getSimpleName());
{
scheduleThreadPool.setRemoveOnCancelPolicy(true);
}
private long loop;
private long logmod = 100;
private final AtomicBoolean started = new AtomicBoolean(false);
private final AtomicBoolean closed = new AtomicBoolean(false);
private ScheduledFuture> future;
@Override
public boolean scheduleWithFixedDelay(long initialDelayMillis, long scheduleMillis) {
if (started.compareAndSet(false, true)) {
future = scheduleThreadPool.scheduleWithFixedDelay(() -> {
scheduling();
}, initialDelayMillis, scheduleMillis, TimeUnit.MILLISECONDS);
return true;
}
return false;
}
@Override
public boolean scheduleAtFixedRate(long initialDelayMillis, long scheduleMillis) {
if (started.compareAndSet(false, true)) {
future = scheduleThreadPool.scheduleAtFixedRate(() -> {
scheduling();
}, initialDelayMillis, scheduleMillis, TimeUnit.MILLISECONDS);
return true;
}
return false;
}
@Override
public boolean scheduleWithCron(String cron) {
Assert.isTrue(CronUtils.isValid(cron), "Invalid:cron");
if (started.compareAndSet(false, true)) {
doCron(cron);
return true;
}
return false;
}
private void doCron(String cron) {
future = scheduleThreadPool.schedule(() -> {
scheduling();
doCron(cron);
}, CronUtils.nextDelayMillis(cron), TimeUnit.MILLISECONDS);
}
private void scheduling() {
synchronized (this) {// 关闭等待用
try {
if (log.isInfoEnabled() && allowLoopLog()) {
log.info("{} schedule run, loop:{}", this.getClass().getSimpleName(), loop);
}
if (isClosed()) {
log.info("{} schedule was closed, stop", this.getClass().getSimpleName());
/**
* 如果已关闭,终止执行
*/
return;
}
doSchedule();
} catch (Throwable e) {
log.warn("ex on {}", AbstractSchedule.this.getClass().getSimpleName(), e);
} finally {
loop++;
}
}
}
protected abstract void doSchedule() throws Throwable;
public void setLogmod(long logmod) {
this.logmod = logmod;
}
protected boolean allowLoopLog() {
return loop % logmod == 0;
}
@Override
public boolean isClosed() {
return closed.get();
}
/**
* 阻塞直到处理完毕,这不会阻塞很久
*/
@Override
public void close() {
if (future != null) {
future.cancel(true);
}
closed.set(true);
/**
* 使用synchronized保障如果任务正在处理中,则等待任务处理完毕
*/
synchronized (this) {
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy