在一系列关联的多任务的实时环境中,如果有一个任务发生失败,可能导致所有任务产生连锁反应,从而造成调度失控的局面。特别是对于核心控制设备尤其重要,为了解决这个问题,必须对每个任务进行实时监控。
在一系列关联的多任务的实时环境中,如果有一个任务发生失败,可能导致所有任务产生连锁反应,从而造成调度失控的局面。特别是对于核心控制设备尤其重要,为了解决这个问题,必须对每个任务进行实时监控。
问题分析
在JAVA环境中,一个任务一般是由一个独立线程来引导实现的,独立线程可能调用一系列子线程。如果在执行过程中,某一个线程发生异常(产生的原因很多,比如软件升级、运行环境改变、系统资抢占等),那么该线程就会停止运行,直到下次任务重新被提交。对于实时环境来说当前任务是失败的。我们无法预测和完全避免异常的发生,但是可以通过一些技术手段来跟踪任务的状态,从而及时发现问题并恢复正常,减少损失。
设计原理
对于一个实时任务而言,执行效率是非常关键的,这意味着不可能考虑用非常复杂的方式来实现任务监控,即使这样可以做的比较完善,同时监控代码本身也会引入一些异常,这就要求监控程序必须简单可靠,能够发现大多数问题,并能及时处理。
一个可能的简单实现。
我们对每个任务加上一个监控的"壳",调度程序调用这个"壳"来完成对具体任务的引导和监控,相当于每个任务具有自治能力。这样做的好处有:
- 分散控制。不需要修改调度主体程序,不增加调度过程的复杂度;
- 控制灵活,安全性高。对于不同任务可定义不同控制方式和控制参数,封装在任务内部,灵活性好,对个别任务控制代码的修改不会影响其他任务,即任务控制实现松藕合,避免错误扩散。适合团队开发;
- 维护简单,升级方便。对于新的任务加入也无需改变原来调度程序的结构,只需修改任务表及相关参数,这样在性能提高的同时也简化了软件升级过程中的代码维护量。
每个线程理论上有四种状态:
new |
线程对象已经创建,但尚未启动,不可运行 |
runnable |
一旦有时间分片机制有空闲的CPU周期,线程立即开始运行 |
dead |
从run()方法退出后,一个线程即消亡 |
blocked |
线程可运行,但有某种东西阻碍了它。调度机制不给它分配任何CPU时间,直到它进入runnable状态 |
在实际操作中,为了便于描述,我们重新规定了线程的状态:
Actived |
线程已被激活,处于运行状态 |
Sleeping |
线程完成一个特定任务后退出,进入休眠状态 |
Dead |
线程运行过程中发生异常,终止运行,处于死亡状态 |
根据上述理论,我们只需要对Actived状态的线程进行监控,也只有对Actived状态监控才有意义,这是对监控模块做出逻辑简化。那么如何实现监控模块对具体任务的监控呢?
对具体任务的监控方式有多种,根据任务的不同,需要采用不同的监控代码,但是在结构上基本相同。这和类的重载概念有点相似。本文附有一个简单的例子。
A任务每秒执行一个简单的代数运算 j = 1/ i,并打印结果。我们故意在其中设置了一个异常陷阱,使得执行过程中出现一次被0除的算术异常,下面结合这个例子讲述监控原理。
为了监控A,我们设计了一个监控线程M。M中定义了一些关键逻辑变量:
Keepchecking |
持续监控标志 |
laststatus |
保存上次监控状态 |
maydeadtimes |
监控线程可能死亡的计数器 |
maydeadtimeout |
定义判断线程死亡的边界条件 |
deadtimes |
监控线程死亡次数的计数器 |
deadtimeout |
定义判断线程不正常的边界条件 |
为了适应监控,在A任务中相应增加一些可以被监控的状态和行为:
dead |
死状态标志 |
dead = !dead; |
改变状态 |
整个监控就是围绕这些状态标志和行为展开的。A任务定期修改自己的dead标志,dead是一个布尔变量,理论上只要A没有死,那么dead肯定是周期变化的(和心跳概念差不多),M需要做的就是监控dead的变化。为了避免一些偶然因素导致的误判,我们在M中设置了一些计数器和边界值(maydeadtimes和maydeadtimeout),当M发现A的可能死亡次数超过一定限制后,判断A已死亡,不在继续等待了,作为实时处理,首先注销A的实例,然后重新启动A(和我们计算机死机的复位很像),然后进入新一轮监控。
如果是因为系统偶然因素导致A死亡,那么在随后的新的任务启动过程中一般可以顺利完成。但是万一由于环境参数改变或软件升级存在版本缺陷,A可能始终会产生异常,那么M是否需要耐心地监控下去呢?一个形象的例子是:如果你连续3次开机都失败,你是否会怀疑机器有问题?当然,你会,那么M也应该会。
为了对A任务重复多次死亡有一个统计,M中又引入了另外对计数器和边界值(deadtimes和deadtimeout),和你开计算机的过程一样,如果连续n次都发现A有问题,可以基本肯定不是由于偶然因素引起的,需要对A的代码或系统的环境进行检查。M会发出告警,通知必须要对A进行审查了,然后清空A,自己自动安全退出。如果在核心调度程序中设置一个标志接受M们的告警,就可以有足够理由终止其他任务的执行。可以看见,在A任务发生异常期间,M承担了核心调度程序的维护功能。特别是当任务数量比较多的情况,核心调度程序只能采用排队方式处理任务异常,而且由于处理异常的复杂程度不同,无法保证对多任务异常的实时处理。
还要考虑正常情况下A和M的关系。核心调度程序通过M启动A任务后,M处于持续监控状态,当A正常结束任务后,A需要通知M结束监控,这样,当A进入休眠状态后,M也不会占用内存空间,提高了系统资源的利用率。
通过以上描述,可以看到,上述监控思想具有清晰的概念和可操作性,占用资源少,为保证系统连续稳定运行创造了条件。
具体代码实现附后。
运行结果如下:
异常情况 |
正常情况 |
i=-3: status=true M read A status = true i=-2: status=false M read A status = false i=-1: status=true M read A status = true A become Exception! M read A status = true M read A status = true M read A status = true A is deaded! M is restarting A! ____________________________ i=-3: status=false M read A status = false i=-2: status=true M read A status = true i=-1: status=false M read A status = false A become Exception! M read A status = false M read A status = false M read A status = false A is deaded! M is restarting A! ____________________________ i=-3: status=true M read A status = true i=-2: status=false M read A status = false i=-1: status=true M read A status = true A become Exception! M read A status = true M read A status = true M read A status = true Alert! A is unstable, M will stop it (结束)
|
i=1: status=true M read A status = true i=2: status=false M read A status = false i=3: status=true M read A status = true i=4: status=false M read A status = false i=5: status=true M read A status = true A is Ending M M read A status = true (结束)
|
package safethread;
// 核心调度程序
public class mythread {
public mythread() { }
public static void main(String[] args) {
M m = new M();
}
}
// A 任务线程
class A extends Thread {
public static boolean dead = false;
M m;
A(M m){
m = m;
start();
}
public void run(){
try{
for(int i=-3;i<= 5;i++){
int j=1/i; // 人为设置过程中陷阱
dead = !dead; // 活动状态
System.out.println("i=" + i + ": status=" + dead);
try{
sleep(2000);
}
catch(InterruptedException ie){
System.out.println("A is Interrupted!");
}
}
m.Keepchecking = false; //A 正常结束后关闭监控线程
System.out.println("A is Ending M");
}
catch(Exception e){
System.out.println("A become Exception!");
}
}
}
// 监控线程
class M extends Thread{
public static boolean Keepchecking = true; // 持续监控标志
boolean laststatus; //保存上次监控状态
int maydeadtimes = 0; //监控线程可能死亡的计数器
int maydeadtimeout = 3;//定义判断线程死亡的边界条件
int deadtimes = 0; //监控线程死亡次数的计数器
int deadtimeout = 3; //定义判断线程不正常的边界条件
A a;
M(){start();}
public void run(){
schedule();
while(Keepchecking){
laststatus = a.dead;
try{
sleep(2000);
}
catch(InterruptedException e){
System.out.println("M is Interrupted!");
}
System.out.println("M read A status = " + a.dead);
if(laststatus == a.dead ){
if(++maydeadtimes >= maydeadtimeout){
if(++deadtimes >= deadtimeout){
System.out.println("Alert! A is unstable, M will stop it");
a = null;
break;
}
else{
System.out.println( "A is deaded!");
schedule();
System.out.println("M is restarting A!\n____________________________\n");
}
}
}
else{
maydeadtimes = 0;
}
}
}
private void schedule(){
A a = new A(this);
}
}
|
结束语
通过给制定任务线程增加监控线程,可以很好地解决实时多任务环境下的安全监控问题,同时避免了核心调度线程事务过分复杂的问题。实践证明,该方法复杂度小,占用资源少,运行可靠,适合复杂条件下的多任务环境。
分享到:
相关推荐
综上所述,基于Java的分布式定时任务调度、管理、监控系统涉及的技术栈广泛,包括任务调度框架、分布式协调、监控、日志、安全等多个方面。这样的系统能够有效地支持大型企业对定时任务的高效管理,提升运维效率,...
jconch是一个基于Java的任务调度框架,它的设计目标是提供一个高效、稳定、易用的解决方案,用于在分布式环境中执行定时任务。在本篇文章中,我们将深入探讨Java任务调度的核心概念,以及jconch如何实现这些功能。 ...
综上所述,设计和实现一个Java版的分布式任务调度系统涉及到多个层面的技术选型和策略规划。通过合理地运用上述组件和设计原则,我们可以构建出高效、可靠的分布式任务执行环境,满足企业级应用的需求。
综上所述,"java-jsp车辆调度管理系统计算机毕业设计"是一个综合性的项目,涵盖了Java编程、Web开发、数据库管理和系统设计等多个方面,对于学习和提升Java Web应用开发技能大有裨益。通过分析和实践该项目,不仅...
EasyScheduler,又称为“易调度”...总的来说,EasyScheduler是一个强大且灵活的分布式任务调度解决方案,尤其适用于需要处理复杂任务依赖关系和实时监控的场景,它的开源特性使得它在大数据平台中具有广泛的应用前景。
虽然简单易用,但`Timer`并不适合高并发场景,因为它不是线程安全的,可能导致多个任务调度混乱。 2. **Quartz库** Quartz是一款开源的作业调度框架,它可以用来按计划执行任务。Quartz支持复杂的调度逻辑,如精确...
SSM分布式任务调度系统是基于Spring、SpringMVC和MyBatis这三大主流Java开发框架构建的高效能、可扩展的任务调度平台。该系统旨在解决大规模集群环境下的任务分配、执行与监控问题,广泛应用于大数据处理、定时任务...
在IT行业中,分布式任务调度是构建大规模系统的关键技术之一,特别是在大数据处理、实时计算和微服务架构中。本文将深入探讨“Hera-Master”这一分布式任务调度框架的源码,帮助开发者理解其核心概念、设计模式以及...
- `java.util.Timer`: 这是Java标准库中提供的一种简单的定时任务调度器,它可以安排一次性或周期性的任务。然而,`Timer`并不适合并发环境,因为它只有一个线程处理所有任务,可能导致任务间的相互阻塞。 - `java...
Java中的定时任务是软件开发中一个非常重要的功能,它允许我们按照预定的时间间隔执行特定的任务,比如数据备份、日志清理、系统监控等。在Java中,我们可以利用`java.util.Timer`类和`java.util.TimerTask`类来实现...
分布式任务调度平台Jobs是针对大型企业或互联网公司设计的一种高效、稳定、可扩展的任务调度解决方案。它基于Java开发,能够支持分布式环境中的任务管理和执行,适用于大数据处理、定时任务、实时计算等多种场景。...
Java-Push开源实时消息推送系统是一种基于Java技术构建的、专为实现高效、稳定、实时的消息推送服务而设计的解决方案。在当今互联网应用中,实时消息推送已经成为提高用户体验和互动性的重要工具,尤其是在社交网络...
8. **任务调度**:系统可能使用Quartz或Spring Scheduler等工具进行定时任务的调度。这些库允许设置定时规则,自动触发任务执行。 9. **权限和安全**:对于企业级系统,权限管理和用户认证是必不可少的。Java任务...
- **安全性**:支持数据加密和权限控制,确保任务调度过程中的数据安全。 - **易用性**:API接口丰富,易于集成到现有的系统中,同时提供详细的文档和示例,方便开发者使用。 3. **功能特性** - **任务调度**:...
《基于SSH的任务调度系统设计与实现》是一个涵盖了Java开发、任务调度、数据库管理和用户界面等多个IT领域的综合性项目。SSH(Spring、Struts、Hibernate)是Java Web开发中的经典框架组合,用于构建高效、灵活的...
从文件名"定时同步系统"推测,该系统可能包含一个定时任务调度组件,如Quartz或Spring Scheduler,用于定期执行数据同步任务。 综上所述,Java数据实时同步系统通过高效的同步策略、可靠的框架和全面的错误处理...
定时任务往往涉及到多线程和并发问题,因此在编写代码时需要考虑线程安全,确保任务的正确性和一致性。 8. **监控与管理** 对于复杂的系统,定时任务的监控和管理同样重要。可能需要记录任务执行日志,或者提供一...
"task"是一个专为企业应用设计的任务调度统一管理平台,它主要通过HTTP协议实现任务的调度。这个特性使得任务能够在网络环境中高效地进行分发和执行,适用于分布式系统中的任务管理和协调。HTTP支持签名算法,这一...
09 Java实时多任务调度过程中的安全监控设计 (3) 10 不要重新分配被锁定对象的对象引用 11 以全局的固定顺序获取多个锁来避免死锁 12 Java单例对象同步问题探讨 13 Java 理论与实践: 描绘线程安全性 (2) 14 ...
【多AGV调度系统软件】是一种先进的自动化物流解决方案,它基于JAVA编程语言开发,能够适应各种操作系统环境,只要这些系统支持Java运行时环境(JRE)。AGV,即自动导引车,是自动化仓库和制造业中广泛使用的移动...