Merge remote-tracking branch 'origin/test' into restruct-new
# Conflicts: # src/main/java/club/joylink/rtss/simulation/job/SimulationScheduledJob.java
This commit is contained in:
commit
4cb457ab16
@ -133,7 +133,12 @@ public abstract class Simulation<U extends SimulationUser, M extends Simulation
|
|||||||
try {
|
try {
|
||||||
this.mainLogicRunning.set(true);
|
this.mainLogicRunning.set(true);
|
||||||
this.systemTime = this.systemTime.plusNanos(timeAdd);
|
this.systemTime = this.systemTime.plusNanos(timeAdd);
|
||||||
this.jobMap.values().forEach(SimulationJob::run);
|
this.jobMap.values().forEach(simulationJob -> {
|
||||||
|
if (getSystemTime().compareTo(simulationJob.runtime) >= 0) {
|
||||||
|
simulationJob.job.run();
|
||||||
|
simulationJob.afterRun();
|
||||||
|
}
|
||||||
|
});
|
||||||
} catch (Throwable e) {
|
} catch (Throwable e) {
|
||||||
this.runError(e);
|
this.runError(e);
|
||||||
log.error(String.format("仿真[%s]主线程逻辑执行异常,仿真停止运行", this.id), e);
|
log.error(String.format("仿真[%s]主线程逻辑执行异常,仿真停止运行", this.id), e);
|
||||||
@ -190,7 +195,7 @@ public abstract class Simulation<U extends SimulationUser, M extends Simulation
|
|||||||
* @param job 仿真逻辑
|
* @param job 仿真逻辑
|
||||||
* @param rate 执行频率,单位ms
|
* @param rate 执行频率,单位ms
|
||||||
*/
|
*/
|
||||||
public void addJob(String name, SimulationJob job, int rate) {
|
public void addJob(String name, Runnable job, int rate) {
|
||||||
if (null == name) {
|
if (null == name) {
|
||||||
throw new IllegalArgumentException("name can't be null");
|
throw new IllegalArgumentException("name can't be null");
|
||||||
}
|
}
|
||||||
@ -207,7 +212,7 @@ public abstract class Simulation<U extends SimulationUser, M extends Simulation
|
|||||||
* @param job 仿真逻辑
|
* @param job 仿真逻辑
|
||||||
* @param rate 执行频率,单位ms
|
* @param rate 执行频率,单位ms
|
||||||
*/
|
*/
|
||||||
public void addFixedRateJob(String name, SimulationJob job, int rate) {
|
public void addFixedRateJob(String name, Runnable job, int rate) {
|
||||||
if (null == name) {
|
if (null == name) {
|
||||||
throw new IllegalArgumentException("name can't be null");
|
throw new IllegalArgumentException("name can't be null");
|
||||||
}
|
}
|
||||||
@ -223,9 +228,9 @@ public abstract class Simulation<U extends SimulationUser, M extends Simulation
|
|||||||
* @param job
|
* @param job
|
||||||
* @param delay
|
* @param delay
|
||||||
*/
|
*/
|
||||||
public void addDelayExecuteJob(SimulationJob job, long delay) {
|
public void addDelayExecuteJob(Runnable job, long delay) {
|
||||||
SimulationDelayJob delayJob = new SimulationDelayJob(this, job, delay);
|
SimulationDelayJob delayJob = new SimulationDelayJob(this, job, delay);
|
||||||
this.jobMap.put(delayJob.getId(), delayJob);
|
this.jobMap.put(delayJob.getName(), delayJob);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -4,48 +4,30 @@ import club.joylink.rtss.simulation.Simulation;
|
|||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
import java.time.LocalDateTime;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Getter
|
@Getter
|
||||||
public final class SimulationDelayJob implements SimulationJob {
|
public final class SimulationDelayJob extends SimulationJob {
|
||||||
private static final AtomicLong ID_SEED = new AtomicLong(0);
|
private static final AtomicLong ID_SEED = new AtomicLong(0);
|
||||||
|
|
||||||
private Simulation simulation;
|
|
||||||
private String id;
|
|
||||||
/**
|
|
||||||
* 运行逻辑
|
|
||||||
*/
|
|
||||||
private SimulationJob job;
|
|
||||||
/**
|
|
||||||
* 执行时间
|
|
||||||
*/
|
|
||||||
private LocalDateTime time;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param simulation
|
* @param simulation
|
||||||
* @param job
|
* @param job
|
||||||
* @param delay - 单位:毫秒
|
* @param delay - 单位:毫秒
|
||||||
*/
|
*/
|
||||||
public SimulationDelayJob(Simulation simulation, SimulationJob job, long delay) {
|
public SimulationDelayJob(Simulation simulation, Runnable job, long delay) {
|
||||||
this.simulation = simulation;
|
super(simulation, generateId(), job, simulation.getSystemTime().plusNanos(TimeUnit.MILLISECONDS.toNanos(delay)));
|
||||||
this.id = generateId();
|
|
||||||
this.job = job;
|
|
||||||
this.time = simulation.getSystemTime().plusNanos(TimeUnit.MILLISECONDS.toNanos(delay));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String generateId() {
|
private static String generateId() {
|
||||||
return String.valueOf(ID_SEED.incrementAndGet());
|
return String.valueOf(ID_SEED.incrementAndGet());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void afterRun() {
|
||||||
if (simulation.getSystemTime().compareTo(this.time) >= 0) {
|
simulation.removeJob(name);
|
||||||
this.job.run();
|
|
||||||
simulation.removeJob(getId());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,15 +3,26 @@ package club.joylink.rtss.simulation.job;
|
|||||||
import club.joylink.rtss.simulation.Simulation;
|
import club.joylink.rtss.simulation.Simulation;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public final class SimulationFixedJob extends SimulationScheduledJob {
|
public final class SimulationFixedJob extends SimulationScheduledJob {
|
||||||
|
|
||||||
public SimulationFixedJob(Simulation simulation, String name, SimulationJob job, int rate) {
|
public SimulationFixedJob(Simulation simulation, String name, Runnable job, int rate) {
|
||||||
super(simulation, name, job, rate);
|
super(simulation, name, job, rate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void afterRun() {
|
||||||
super.doRun((rate, speed) -> rate * speed);
|
LocalDateTime systemTime = simulation.getSystemTime();
|
||||||
|
// 实际运行间隔,单位ns
|
||||||
|
long runPeriod = TimeUnit.MILLISECONDS.toNanos(this.rate) * simulation.getSpeed();
|
||||||
|
// 弥补非整数倍的情况
|
||||||
|
long l = Duration.between(this.runtime, systemTime).toNanos();
|
||||||
|
long l1 = l % runPeriod;
|
||||||
|
long add = runPeriod - l1;
|
||||||
|
this.runtime = systemTime.plusNanos(add);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,32 @@
|
|||||||
package club.joylink.rtss.simulation.job;
|
package club.joylink.rtss.simulation.job;
|
||||||
|
|
||||||
public interface SimulationJob {
|
import club.joylink.rtss.simulation.Simulation;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
void run();
|
import java.time.LocalDateTime;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public abstract class SimulationJob {
|
||||||
|
Simulation simulation;
|
||||||
|
public String name;
|
||||||
|
/**
|
||||||
|
* 运行逻辑
|
||||||
|
*/
|
||||||
|
public Runnable job;
|
||||||
|
/**
|
||||||
|
* 执行时间
|
||||||
|
*/
|
||||||
|
public LocalDateTime runtime;
|
||||||
|
|
||||||
|
public SimulationJob(Simulation simulation, String name, Runnable job, LocalDateTime runtime) {
|
||||||
|
if (null == job) {
|
||||||
|
throw new IllegalArgumentException("job must not be null");
|
||||||
|
}
|
||||||
|
this.simulation = simulation;
|
||||||
|
this.name = name;
|
||||||
|
this.job = job;
|
||||||
|
this.runtime = runtime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public abstract void afterRun();
|
||||||
}
|
}
|
||||||
|
@ -6,69 +6,24 @@ import lombok.extern.slf4j.Slf4j;
|
|||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.function.BiFunction;
|
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class SimulationScheduledJob implements SimulationJob {
|
public class SimulationScheduledJob extends SimulationJob {
|
||||||
Simulation simulation;
|
|
||||||
private String name;
|
|
||||||
/**
|
|
||||||
* 运行逻辑
|
|
||||||
*/
|
|
||||||
private SimulationJob job;
|
|
||||||
/**
|
/**
|
||||||
* 原始频率,单位ms
|
* 原始频率,单位ms
|
||||||
*/
|
*/
|
||||||
final int rate;
|
final int rate;
|
||||||
|
|
||||||
LocalDateTime nextRunTime; // 下次需要执行的时刻(后续基于性能考虑可换为long类型)
|
public SimulationScheduledJob(Simulation simulation, String name, Runnable job, int rate) {
|
||||||
|
super(simulation, name, job, simulation.getSystemTime());
|
||||||
public SimulationScheduledJob(Simulation simulation, String name, SimulationJob job, int rate) {
|
|
||||||
if (null == job) {
|
|
||||||
throw new IllegalArgumentException("job must not be null");
|
|
||||||
}
|
|
||||||
if (rate <= 0) {
|
if (rate <= 0) {
|
||||||
throw new IllegalArgumentException("rate must bigger than 0");
|
throw new IllegalArgumentException("rate must bigger than 0");
|
||||||
}
|
}
|
||||||
this.simulation = simulation;
|
|
||||||
this.name = name;
|
|
||||||
this.job = job;
|
|
||||||
this.rate = rate;
|
this.rate = rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final long TIMEOUT_NANO = TimeUnit.MILLISECONDS.toNanos(5);
|
public static final long TIMEOUT_NANO = TimeUnit.MILLISECONDS.toNanos(5);
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
doRun((rate, speed) -> rate);
|
|
||||||
}
|
|
||||||
|
|
||||||
void doRun(BiFunction<Long, Integer, Long> consumer) {
|
|
||||||
LocalDateTime systemTime = simulation.getSystemTime();
|
|
||||||
if (this.nextRunTime == null || systemTime.compareTo(this.nextRunTime) >= 0) {
|
|
||||||
long start = System.nanoTime();
|
|
||||||
this.job.run();
|
|
||||||
long used = System.nanoTime() - start;
|
|
||||||
if (used > TIMEOUT_NANO) {
|
|
||||||
log.warn(String.format("仿真任务[%s]执行耗时[%sms]超过[%sms],请检查并调优",
|
|
||||||
this.name, TimeUnit.NANOSECONDS.toMillis(used), TimeUnit.NANOSECONDS.toMillis(TIMEOUT_NANO)));
|
|
||||||
}
|
|
||||||
// 实际运行间隔,单位ns
|
|
||||||
Long runPeriod = consumer.apply(TimeUnit.MILLISECONDS.toNanos(this.rate), simulation.getSpeed());
|
|
||||||
if (this.nextRunTime != null) {
|
|
||||||
// 弥补非整数倍的情况
|
|
||||||
long l = Duration.between(this.nextRunTime, systemTime).toNanos();
|
|
||||||
long l1 = l % runPeriod;
|
|
||||||
long add = runPeriod - l1;
|
|
||||||
this.nextRunTime = systemTime.plusNanos(add);
|
|
||||||
} else {
|
|
||||||
this.nextRunTime = systemTime.plusNanos(runPeriod);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@ -78,4 +33,16 @@ public class SimulationScheduledJob implements SimulationJob {
|
|||||||
public int calculateRunTimes(long interval) {
|
public int calculateRunTimes(long interval) {
|
||||||
return (int) (interval / TimeUnit.MILLISECONDS.toNanos(this.rate));
|
return (int) (interval / TimeUnit.MILLISECONDS.toNanos(this.rate));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afterRun() {
|
||||||
|
LocalDateTime systemTime = simulation.getSystemTime();
|
||||||
|
// 实际运行间隔,单位ns
|
||||||
|
long runPeriod = TimeUnit.MILLISECONDS.toNanos(this.rate);
|
||||||
|
// 弥补非整数倍的情况
|
||||||
|
long l = Duration.between(this.runtime, systemTime).toNanos();
|
||||||
|
long l1 = l % runPeriod;
|
||||||
|
long add = runPeriod - l1;
|
||||||
|
this.runtime = systemTime.plusNanos(add);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user