Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
Z
zhmes-agecal
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
耿迪迪
zhmes-agecal
Commits
bdb2918e
Commit
bdb2918e
authored
Sep 24, 2025
by
wanghao
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Revert "1 测试 上电后通信 和 最终完成 定时任务功能"
parent
a80d6ec5
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
221 additions
and
164 deletions
+221
-164
DeviceStatusReaderAndTimeSetter.java
...stem/modbus/business/DeviceStatusReaderAndTimeSetter.java
+76
-66
TStoreyInfoServiceImpl.java
...om/zehong/system/service/impl/TStoreyInfoServiceImpl.java
+1
-1
DeviceCommunicationJob.java
...n/java/com/zehong/system/task/DeviceCommunicationJob.java
+78
-66
DeviceTaskScheduler.java
...main/java/com/zehong/system/task/DeviceTaskScheduler.java
+66
-31
No files found.
zhmes-agecal-system/src/main/java/com/zehong/system/modbus/business/DeviceStatusReaderAndTimeSetter.java
View file @
bdb2918e
This diff is collapsed.
Click to expand it.
zhmes-agecal-system/src/main/java/com/zehong/system/service/impl/TStoreyInfoServiceImpl.java
View file @
bdb2918e
...
@@ -342,7 +342,7 @@ public class TStoreyInfoServiceImpl implements ITStoreyInfoService
...
@@ -342,7 +342,7 @@ public class TStoreyInfoServiceImpl implements ITStoreyInfoService
}
else
{
}
else
{
registerOffset
=
Arrays
.
asList
(
55
,
56
,
57
,
58
,
59
,
60
,
61
,
62
,
63
,
64
,
65
,
66
,
67
,
68
,
69
,
70
,
71
,
72
);
registerOffset
=
Arrays
.
asList
(
55
,
56
,
57
,
58
,
59
,
60
,
61
,
62
,
63
,
64
,
65
,
66
,
67
,
68
,
69
,
70
,
71
,
72
);
}
}
deviceStatusReaderAndTimeSetter
.
startMultiDeviceMonitoring
(
split
[
0
],
Integer
.
parseInt
(
split
[
1
]),
registerOffset
,
modbusResultHandler
,
ModbusResultHandler
.
createDefaultStopCondition
());
//
deviceStatusReaderAndTimeSetter.startMultiDeviceMonitoring(split[0], Integer.parseInt(split[1]),registerOffset, modbusResultHandler, ModbusResultHandler.createDefaultStopCondition());
return
null
;
return
null
;
...
...
zhmes-agecal-system/src/main/java/com/zehong/system/task/DeviceCommunicationJob.java
View file @
bdb2918e
This diff is collapsed.
Click to expand it.
zhmes-agecal-system/src/main/java/com/zehong/system/task/DeviceTaskScheduler.java
View file @
bdb2918e
...
@@ -31,8 +31,12 @@ public class DeviceTaskScheduler {
...
@@ -31,8 +31,12 @@ public class DeviceTaskScheduler {
// 新增:每个设备任务的Quartz线程隔离(避免任务间干扰)
// 新增:每个设备任务的Quartz线程隔离(避免任务间干扰)
private
static
final
String
THREAD_GROUP
=
"DEVICE_THREAD_GROUP"
;
private
static
final
String
THREAD_GROUP
=
"DEVICE_THREAD_GROUP"
;
// 常量:Cron周期(5分钟)、任务有效期(7天)
private
static
final
String
CRON_EXPRESSION
=
"0 0/5 * * * ?"
;
private
static
final
int
TASK_VALID_DAYS
=
7
;
/**
/**
* 创建设备监控任务(入口
方法
)
* 创建设备监控任务(入口
:增加调度器健康检查、任务去重
)
*/
*/
public
void
scheduleDeviceMonitoring
(
Long
fStoreyId
,
String
fPowerOutageIp
,
Integer
fPowerOutagePort
)
{
public
void
scheduleDeviceMonitoring
(
Long
fStoreyId
,
String
fPowerOutageIp
,
Integer
fPowerOutagePort
)
{
if
(
fStoreyId
==
null
||
fPowerOutageIp
==
null
||
fPowerOutagePort
==
null
)
{
if
(
fStoreyId
==
null
||
fPowerOutageIp
==
null
||
fPowerOutagePort
==
null
)
{
...
@@ -43,63 +47,64 @@ public class DeviceTaskScheduler {
...
@@ -43,63 +47,64 @@ public class DeviceTaskScheduler {
try
{
try
{
log
.
info
(
"=== 开始创建设备监控任务:fStoreyId={} ==="
,
fStoreyId
);
log
.
info
(
"=== 开始创建设备监控任务:fStoreyId={} ==="
,
fStoreyId
);
// 1. 确保调度器已启动(若依框架可能延迟启动)
// 1. 调度器健康检查(确保线程池可用)
if
(!
scheduler
.
isStarted
())
{
checkSchedulerHealth
();
log
.
warn
(
"调度器未启动,手动启动..."
);
scheduler
.
start
();
}
// 关键:添加调度器状态监控,确保线程池可用
// 2. 任务去重(避免重复创建导致资源竞争)
SchedulerMetaData
metaData
=
scheduler
.
getMetaData
();
if
(
isTaskExists
(
"COMM_"
+
fStoreyId
))
{
log
.
info
(
"Quartz线程池状态:核心线程={} 任务总数={}"
,
log
.
info
(
"通信任务[COMM_{}]已存在,无需重复创建"
,
fStoreyId
);
metaData
.
getThreadPoolSize
(),
// 检查现有触发器状态,若为ERROR则重建
metaData
.
getNumberOfJobsExecuted
());
if
(
isTriggerError
(
"COMM_"
+
fStoreyId
))
{
log
.
warn
(
"通信任务[COMM_{}]触发器状态为ERROR,重建触发器"
,
fStoreyId
);
createHourlyCommunicationJob
(
fStoreyId
);
}
return
;
}
//
2. 创建两个
核心任务
//
3. 创建
核心任务
createHourlyCommunicationJob
(
fStoreyId
);
createHourlyCommunicationJob
(
fStoreyId
);
createFinalExecutionJob
(
fStoreyId
,
fPowerOutageIp
,
fPowerOutagePort
);
createFinalExecutionJob
(
fStoreyId
,
fPowerOutageIp
,
fPowerOutagePort
);
// 3. 验证任务是否创建成功(关键:打印触发器状态)
checkTaskStatus
(
fStoreyId
);
checkTaskStatus
(
fStoreyId
);
log
.
info
(
"=== 设备监控任务创建完成:fStoreyId={} ==="
,
fStoreyId
);
log
.
info
(
"=== 设备监控任务创建完成:fStoreyId={} ==="
,
fStoreyId
);
}
catch
(
SchedulerException
e
)
{
}
catch
(
SchedulerException
e
)
{
log
.
error
(
"=== 创建设备监控任务失败:fStoreyId={} ==="
,
fStoreyId
,
e
);
log
.
error
(
"=== 创建设备监控任务失败:fStoreyId={} ==="
,
fStoreyId
,
e
);
cleanInvalidTask
(
fStoreyId
);
// 失败时清理残留
throw
new
RuntimeException
(
"Quartz任务调度失败"
,
e
);
throw
new
RuntimeException
(
"Quartz任务调度失败"
,
e
);
}
}
}
}
/**
/**
* 1. 创建每
2分钟执行的通信任务(CronTrigger
)
* 1. 创建每
5分钟执行的通信任务(核心优化:简化调度逻辑、调整Misfire策略
)
*/
*/
private
void
createHourlyCommunicationJob
(
Long
fStoreyId
)
throws
SchedulerException
{
private
void
createHourlyCommunicationJob
(
Long
fStoreyId
)
throws
SchedulerException
{
String
jobId
=
"COMM_"
+
fStoreyId
;
String
jobId
=
"COMM_"
+
fStoreyId
;
JobKey
jobKey
=
new
JobKey
(
jobId
,
JOB_GROUP
);
JobKey
jobKey
=
new
JobKey
(
jobId
,
JOB_GROUP
);
TriggerKey
triggerKey
=
new
TriggerKey
(
jobId
+
"_TRIGGER"
,
TRIGGER_GROUP
);
TriggerKey
triggerKey
=
new
TriggerKey
(
jobId
+
"_TRIGGER"
,
TRIGGER_GROUP
);
// 1. 构建JobDetail(仅
定义任务元数据,不涉及调度规则
)
// 1. 构建JobDetail(仅
元数据,禁止并发执行通过注解控制
)
JobDetail
job
=
JobBuilder
.
newJob
(
DeviceCommunicationJob
.
class
)
JobDetail
job
=
JobBuilder
.
newJob
(
DeviceCommunicationJob
.
class
)
.
withIdentity
(
jobKey
)
.
withIdentity
(
jobKey
)
.
withDescription
(
"设备"
+
fStoreyId
+
"每5分钟Modbus通信任务"
)
.
withDescription
(
"设备"
+
fStoreyId
+
"每5分钟Modbus通信任务"
)
.
usingJobData
(
"fStoreyId"
,
fStoreyId
.
toString
())
.
usingJobData
(
"fStoreyId"
,
fStoreyId
.
toString
())
// 传递参数(String避免类型问题)
.
storeDurably
(
false
)
.
storeDurably
(
false
)
// 触发器删除后Job自动失效
.
requestRecovery
(
true
)
// 服务重启后恢复未完成任务
.
requestRecovery
(
true
)
// 服务重启后恢复未完成任务
.
build
();
// 移除错误的 withSchedule() 调用
.
build
();
// 2. 构建CronTrigger(
调度规则在此配置
)
// 2. 构建CronTrigger(
移除withMisfireThreshold,兼容低版本
)
CronTrigger
trigger
=
TriggerBuilder
.
newTrigger
()
CronTrigger
trigger
=
TriggerBuilder
.
newTrigger
()
.
withIdentity
(
triggerKey
)
.
withIdentity
(
triggerKey
)
.
forJob
(
jobKey
)
.
forJob
(
jobKey
)
.
withDescription
(
"设备"
+
fStoreyId
+
"通信任务触发器(每5分钟)"
)
.
withDescription
(
"设备"
+
fStoreyId
+
"通信任务触发器(每5分钟)"
)
.
withSchedule
(
CronScheduleBuilder
.
cronSchedule
(
"0 0/5 * * * ?"
)
.
withSchedule
(
CronScheduleBuilder
.
cronSchedule
(
CRON_EXPRESSION
)
//
关键:Misfire策略(错过触发后忽略,避免集中执行
)
//
Misfire策略:错过触发后立即执行,再按原计划(低版本支持
)
.
withMisfireHandlingInstruction
DoNothing
())
.
withMisfireHandlingInstruction
FireAndProceed
())
.
startNow
()
.
startNow
()
.
endAt
(
Date
.
from
(
Instant
.
now
().
plus
(
7
,
ChronoUnit
.
DAYS
)))
// 7天有效期
.
endAt
(
Date
.
from
(
Instant
.
now
().
plus
(
TASK_VALID_DAYS
,
ChronoUnit
.
DAYS
)))
.
build
();
.
build
();
// 3. 原子操作:创建/更新
任务
// 3. 原子操作:创建/更新
(优先更新,避免删除重建)
if
(
scheduler
.
checkExists
(
jobKey
))
{
if
(
scheduler
.
checkExists
(
jobKey
))
{
Date
nextFireTime
=
scheduler
.
rescheduleJob
(
triggerKey
,
trigger
);
Date
nextFireTime
=
scheduler
.
rescheduleJob
(
triggerKey
,
trigger
);
log
.
info
(
"通信任务[{}]更新触发器成功,下次执行时间:{}"
,
jobId
,
nextFireTime
);
log
.
info
(
"通信任务[{}]更新触发器成功,下次执行时间:{}"
,
jobId
,
nextFireTime
);
...
@@ -109,15 +114,15 @@ public class DeviceTaskScheduler {
...
@@ -109,15 +114,15 @@ public class DeviceTaskScheduler {
}
}
}
}
/**
/**
* 2. 创建
5分钟后执行的最终任务(SimpleTrigger,仅执行一次
)
* 2. 创建
15分钟后执行的最终任务(保持原逻辑,优化超时
)
*/
*/
private
void
createFinalExecutionJob
(
Long
fStoreyId
,
String
fPowerOutageIp
,
Integer
fPowerOutagePort
)
throws
SchedulerException
{
private
void
createFinalExecutionJob
(
Long
fStoreyId
,
String
fPowerOutageIp
,
Integer
fPowerOutagePort
)
throws
SchedulerException
{
String
jobId
=
"FINAL_"
+
fStoreyId
;
String
jobId
=
"FINAL_"
+
fStoreyId
;
JobKey
jobKey
=
new
JobKey
(
jobId
,
JOB_GROUP
);
JobKey
jobKey
=
new
JobKey
(
jobId
,
JOB_GROUP
);
TriggerKey
triggerKey
=
new
TriggerKey
(
jobId
+
"_TRIGGER"
,
TRIGGER_GROUP
);
TriggerKey
triggerKey
=
new
TriggerKey
(
jobId
+
"_TRIGGER"
,
TRIGGER_GROUP
);
// 构建JobDetail
JobDetail
job
=
JobBuilder
.
newJob
(
FinalExecutionJob
.
class
)
JobDetail
job
=
JobBuilder
.
newJob
(
FinalExecutionJob
.
class
)
.
withIdentity
(
jobKey
)
.
withIdentity
(
jobKey
)
.
withDescription
(
"设备"
+
fStoreyId
+
"最终执行任务(仅一次)"
)
.
withDescription
(
"设备"
+
fStoreyId
+
"最终执行任务(仅一次)"
)
...
@@ -128,7 +133,6 @@ public class DeviceTaskScheduler {
...
@@ -128,7 +133,6 @@ public class DeviceTaskScheduler {
.
requestRecovery
(
true
)
.
requestRecovery
(
true
)
.
build
();
.
build
();
// 构建SimpleTrigger
Date
executeTime
=
Date
.
from
(
Instant
.
now
().
plus
(
15
,
ChronoUnit
.
MINUTES
));
Date
executeTime
=
Date
.
from
(
Instant
.
now
().
plus
(
15
,
ChronoUnit
.
MINUTES
));
SimpleTrigger
trigger
=
TriggerBuilder
.
newTrigger
()
SimpleTrigger
trigger
=
TriggerBuilder
.
newTrigger
()
.
withIdentity
(
triggerKey
)
.
withIdentity
(
triggerKey
)
...
@@ -136,11 +140,10 @@ public class DeviceTaskScheduler {
...
@@ -136,11 +140,10 @@ public class DeviceTaskScheduler {
.
withDescription
(
"设备"
+
fStoreyId
+
"最终任务触发器"
)
.
withDescription
(
"设备"
+
fStoreyId
+
"最终任务触发器"
)
.
startAt
(
executeTime
)
.
startAt
(
executeTime
)
.
withSchedule
(
SimpleScheduleBuilder
.
simpleSchedule
()
.
withSchedule
(
SimpleScheduleBuilder
.
simpleSchedule
()
.
withMisfireHandlingInstructionFireNow
()
// 错过
触发
立即执行
.
withMisfireHandlingInstructionFireNow
()
// 错过立即执行
.
withRepeatCount
(
0
))
// 仅
执行
一次
.
withRepeatCount
(
0
))
// 仅一次
.
build
();
.
build
();
// 原子操作:创建/更新
if
(
scheduler
.
checkExists
(
jobKey
))
{
if
(
scheduler
.
checkExists
(
jobKey
))
{
Date
nextFireTime
=
scheduler
.
rescheduleJob
(
triggerKey
,
trigger
);
Date
nextFireTime
=
scheduler
.
rescheduleJob
(
triggerKey
,
trigger
);
log
.
info
(
"最终任务[{}]更新触发器成功,执行时间:{}"
,
jobId
,
nextFireTime
);
log
.
info
(
"最终任务[{}]更新触发器成功,执行时间:{}"
,
jobId
,
nextFireTime
);
...
@@ -149,6 +152,38 @@ public class DeviceTaskScheduler {
...
@@ -149,6 +152,38 @@ public class DeviceTaskScheduler {
log
.
info
(
"最终任务[{}]创建成功,执行时间:{}"
,
jobId
,
nextFireTime
);
log
.
info
(
"最终任务[{}]创建成功,执行时间:{}"
,
jobId
,
nextFireTime
);
}
}
}
}
// ------------------------------ 工具方法:增强稳定性 ------------------------------
/**
* 检查Quartz调度器健康状态(避免线程池耗尽)
*/
private
void
checkSchedulerHealth
()
throws
SchedulerException
{
if
(!
scheduler
.
isStarted
())
{
log
.
warn
(
"调度器未启动,手动启动..."
);
scheduler
.
start
();
}
SchedulerMetaData
metaData
=
scheduler
.
getMetaData
();
// 低版本兼容:获取线程池大小和已执行任务数(替代活跃线程数)
int
poolSize
=
metaData
.
getThreadPoolSize
();
long
executedJobs
=
metaData
.
getNumberOfJobsExecuted
();
log
.
info
(
"Quartz健康状态:线程池大小={}, 已执行任务数={}"
,
poolSize
,
executedJobs
);
// 线程池大小预警(根据实际需求调整阈值)
if
(
poolSize
<
5
)
{
log
.
warn
(
"Quartz线程池过小(当前={}),可能导致任务延迟"
,
poolSize
);
}
}
/**
* 检查触发器是否为ERROR状态
*/
private
boolean
isTriggerError
(
String
jobId
)
throws
SchedulerException
{
TriggerKey
triggerKey
=
new
TriggerKey
(
jobId
+
"_TRIGGER"
,
TRIGGER_GROUP
);
if
(!
scheduler
.
checkExists
(
triggerKey
))
{
return
false
;
}
Trigger
.
TriggerState
state
=
scheduler
.
getTriggerState
(
triggerKey
);
return
state
==
Trigger
.
TriggerState
.
ERROR
;
}
/**
/**
* 检查任务是否已存在(避免重复创建)
* 检查任务是否已存在(避免重复创建)
*/
*/
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment