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:
walker-sheng 2021-05-11 15:06:42 +08:00
commit 4cb457ab16
5 changed files with 74 additions and 83 deletions

View File

@ -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);
}
/**

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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();
}

View File

@ -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);
}
}