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 {
|
||||
this.mainLogicRunning.set(true);
|
||||
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) {
|
||||
this.runError(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 rate 执行频率,单位ms
|
||||
*/
|
||||
public void addJob(String name, SimulationJob job, int rate) {
|
||||
public void addJob(String name, Runnable job, int rate) {
|
||||
if (null == name) {
|
||||
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 rate 执行频率,单位ms
|
||||
*/
|
||||
public void addFixedRateJob(String name, SimulationJob job, int rate) {
|
||||
public void addFixedRateJob(String name, Runnable job, int rate) {
|
||||
if (null == name) {
|
||||
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 delay
|
||||
*/
|
||||
public void addDelayExecuteJob(SimulationJob job, long delay) {
|
||||
public void addDelayExecuteJob(Runnable job, long 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.extern.slf4j.Slf4j;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
@Slf4j
|
||||
@Getter
|
||||
public final class SimulationDelayJob implements SimulationJob {
|
||||
public final class SimulationDelayJob extends SimulationJob {
|
||||
private static final AtomicLong ID_SEED = new AtomicLong(0);
|
||||
|
||||
private Simulation simulation;
|
||||
private String id;
|
||||
/**
|
||||
* 运行逻辑
|
||||
*/
|
||||
private SimulationJob job;
|
||||
/**
|
||||
* 执行时间
|
||||
*/
|
||||
private LocalDateTime time;
|
||||
|
||||
/**
|
||||
*
|
||||
* @param simulation
|
||||
* @param job
|
||||
* @param delay - 单位:毫秒
|
||||
*/
|
||||
public SimulationDelayJob(Simulation simulation, SimulationJob job, long delay) {
|
||||
this.simulation = simulation;
|
||||
this.id = generateId();
|
||||
this.job = job;
|
||||
this.time = simulation.getSystemTime().plusNanos(TimeUnit.MILLISECONDS.toNanos(delay));
|
||||
public SimulationDelayJob(Simulation simulation, Runnable job, long delay) {
|
||||
super(simulation, generateId(), job, simulation.getSystemTime().plusNanos(TimeUnit.MILLISECONDS.toNanos(delay)));
|
||||
}
|
||||
|
||||
public static String generateId() {
|
||||
private static String generateId() {
|
||||
return String.valueOf(ID_SEED.incrementAndGet());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
if (simulation.getSystemTime().compareTo(this.time) >= 0) {
|
||||
this.job.run();
|
||||
simulation.removeJob(getId());
|
||||
}
|
||||
public void afterRun() {
|
||||
simulation.removeJob(name);
|
||||
}
|
||||
}
|
||||
|
@ -3,15 +3,26 @@ package club.joylink.rtss.simulation.job;
|
||||
import club.joylink.rtss.simulation.Simulation;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
@Slf4j
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
super.doRun((rate, speed) -> rate * speed);
|
||||
public void afterRun() {
|
||||
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;
|
||||
|
||||
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.LocalDateTime;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.BiFunction;
|
||||
|
||||
@Slf4j
|
||||
public class SimulationScheduledJob implements SimulationJob {
|
||||
Simulation simulation;
|
||||
private String name;
|
||||
/**
|
||||
* 运行逻辑
|
||||
*/
|
||||
private SimulationJob job;
|
||||
public class SimulationScheduledJob extends SimulationJob {
|
||||
|
||||
/**
|
||||
* 原始频率,单位ms
|
||||
*/
|
||||
final int rate;
|
||||
|
||||
LocalDateTime nextRunTime; // 下次需要执行的时刻(后续基于性能考虑可换为long类型)
|
||||
|
||||
public SimulationScheduledJob(Simulation simulation, String name, SimulationJob job, int rate) {
|
||||
if (null == job) {
|
||||
throw new IllegalArgumentException("job must not be null");
|
||||
}
|
||||
public SimulationScheduledJob(Simulation simulation, String name, Runnable job, int rate) {
|
||||
super(simulation, name, job, simulation.getSystemTime());
|
||||
if (rate <= 0) {
|
||||
throw new IllegalArgumentException("rate must bigger than 0");
|
||||
}
|
||||
this.simulation = simulation;
|
||||
this.name = name;
|
||||
this.job = job;
|
||||
this.rate = rate;
|
||||
}
|
||||
|
||||
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) {
|
||||
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