任务调度的简单实现

做了个简单的任务调度实例,主要思想功能如下:
模拟master和slave2台机器,master机器有一个任务队列,通过启动一个线程定时轮询改任务队列,如果其中有任务,则调用slave的接口将任务分配给slave机器处理。同时,slave机器配置了心跳检测,即slave启动一个线程,每隔一段时间调用master的接口修改master的全局变量lasterAliveTime的值为当前时间,同时,master也有一个线程用来定时计数当前时间与这个lasterAliveTime的时间差,如果超过2秒则认为slave机器死亡。
实现代码如下:


Master包下为master机器运行的类,Slave包下为slave机器运行的类。

模拟2个服务的方法如下;

1.模拟master服务:

在pom.xml里使用jetty插件,并设定端口为8081,如下:

 

<plugins>

<!-- jetty插件 -->

<plugin>

<groupId>org.mortbay.jetty</groupId>

<artifactId>maven-jetty-plugin</artifactId>

<version>6.1.22</version>

<configuration>

<contextPath>/</contextPath>

<connectors>

<connector implementation="org.mortbay.jetty.nio.SelectChannelConnector">

<port>8081</port>

<maxIdleTime>60000</maxIdleTime>

</connector>

</connectors>

<requestLog implementation="org.mortbay.jetty.NCSARequestLog">

<filename>target/access.log</filename>

<retainDays>90</retainDays>

<append>false</append>

<extended>false</extended>

<logTimeZone>GMT+8:00</logTimeZone>

</requestLog>

<systemProperties>

<systemProperty>

<name>productionMode</name>

<value>false</value>

</systemProperty>

</systemProperties>

</configuration>

</plugin>

<plugins>

 

本实例通过实现ServletContextListener接口实现服务启动后自动启动相关类功能,所以配置web.xml如下:

 

<?xml version="1.0" encoding="GB2312"?>

<web-app id="WebApp_ID" version="2.4"

xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

 

<servlet>

<servlet-name>test</servlet-name>

<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

<load-on-startup>1</load-on-startup>

</servlet>

 

<servlet-mapping>

<servlet-name>test</servlet-name>

<url-pattern>/service/*</url-pattern>

</servlet-mapping>

 

 

<context-param>

<param-name>contextConfigLocation</param-name>

<param-value>

   classpath*:/spring/*.xml</param-value>

</context-param>

 

<listener>

<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

</listener>

 

<!--随着服务启动自动运行-->

<listener>

               <listener-class>com.TaskScheduling.Master.AutoRun</listener-class>

        </listener>

 

</web-app>

运行mvn jetty:run命令启动master服务。

2.模拟slave机器
除了web.xml文件外其他代码无需改动,web.xml需修改的配置如下:

        <listener>

               <listener-class>com.TaskScheduling.Slave.SlaveAutoRun</listener-class>

        </listener>

 

运行mvn clean install ,将生成的war包放到jetty的%jetty_home%/webapps路径下,jetty默认的端口为8080,启动jetty,在%jetty_home%下执行命令:java -jar start.jar。

 

 

相关代码如下:

web.xml:

 

<?xml version="1.0" encoding="GB2312"?>

<web-app id="WebApp_ID" version="2.4"

xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

 

<servlet>

<servlet-name>test</servlet-name>

<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>

<load-on-startup>1</load-on-startup>

</servlet>

 

<servlet-mapping>

<servlet-name>test</servlet-name>

<url-pattern>/service/*</url-pattern>

</servlet-mapping>

 

 

<context-param>

<param-name>contextConfigLocation</param-name>

<param-value>

   classpath*:/spring/*.xml</param-value>

</context-param>

 

<listener>

<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>

</listener>

 

        <welcome-file-list>

<welcome-file>/jsp/login.jsp</welcome-file>

</welcome-file-list>

<listener>

    <listener-class>com.TaskScheduling.Master.AutoRun</listener-class>

<!--    <listener-class>com.TaskScheduling.Slave.SlaveAutoRun</listener-class>-->

    </listener>

 

 

 

</web-app>

 

在%classpath%/spring/autorun.xml:

 

 

<?xml version="1.0" encoding="utf-8"?>

 

<beans default-autowire="byName"

xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:aop="http://www.springframework.org/schema/aop" xmlns:util="http://www.springframework.org/schema/util"

xsi:schemaLocation="http://www.springframework.org/schema/beans 

http://www.springframework.org/schema/beans/spring-beans-2.0.xsd 

http://www.springframework.org/schema/aop 

http://www.springframework.org/schema/aop/spring-aop-2.0.xsd 

http://www.springframework.org/schema/util 

http://www.springframework.org/schema/util/spring-util-2.5.xsd ">

 

 

<bean id="jobService" class="com.TaskScheduling.Master.JobService"/>

 

<bean id="heartBeatCheck" class="com.TaskScheduling.Master.HeartBeatCheck" />

<bean id="slaveHeartBeat" class="com.TaskScheduling.Master.impl.SlaveHeartBeatImpl" />

<bean id="heartBeat" class="com.TaskScheduling.Slave.HeartBeat" />

 

        <bean id="testService" class="com.TaskScheduling.Slave.service.TestService" />

 

<bean name="/HeatBeat"

class="org.springframework.remoting.caucho.HessianServiceExporter">

<property name="service" ref="slaveHeartBeat" />

<property name="serviceInterface" value="com.TaskScheduling.Master.SlaveHeartBeat" />

</bean>

 

<bean name="/JobProcess"

class="org.springframework.remoting.caucho.HessianServiceExporter">

<property name="service" ref="jobProcess" />

<property name="serviceInterface" value="com.TaskScheduling.Slave.JobProcess" />

</bean>

 

<bean id="jobProcess" class="com.TaskScheduling.Slave.impl.JobProcessImpl" />

 

</beans>

 

master相关类:

com.TaskScheduling.Master.SlaveHeartBeat:

 

package com.TaskScheduling.Master;

 

public interface SlaveHeartBeat {

public String check() ;

}


com.TaskScheduling.Master.impl.SlaveHeartBeatImpl:
package com.TaskScheduling.Master.impl;

import java.util.Date;

import com.TaskScheduling.Master.MasterGlobalResource;
import com.TaskScheduling.Master.SlaveHeartBeat;

public class SlaveHeartBeatImpl implements SlaveHeartBeat {
/**
* slave定期调用master的该接口修改master的全局变量MasterGlobalResource的Lastalivetime值
*/
public String check() {
MasterGlobalResource.setLastalivetime(new Date());
System.out.println(MasterGlobalResource.getLastalivetime());
return "OK";
}
}

com.TaskScheduling.Master.AutoRun:
package com.TaskScheduling.Master;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.http.HttpServlet;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;


@SuppressWarnings("serial")
public class AutoRun extends HttpServlet implements ServletContextListener {
/**
 * 服务器停止前自动执行
 */
@Override
public void contextDestroyed(ServletContextEvent arg0) {
 DeleteFile();
}
/**
* 服务器启动后自动运行
*/
@Override
public void contextInitialized(ServletContextEvent arg0) {
WriteFile();
/*也可以通过 ApplicationContext app = WebApplicationContextUtils.getWebApplicationContext(arg0.getServletContext()); 获取spring上下文,
但不可以通过让AutoRun 类实现ApplicationContextAware接口来获取上下文,应为autorun类实现了ServletContextListener,所以在sp ring启动前启动,所以得到的上下文将为null*/
                 ApplicationContext app = new ClassPathXmlApplicationContext("classpath*:spring/*.xml");
//任务队列轮询
MasterGlobalResource.getExecutor().execute((JobService)app.getBean("jobService"));
//检测slave机器是否存活
MasterGlobalResource.getExecutor().execute((HeartBeatCheck)app.getBean("heartBeatCheck"));
}
 public void WriteFile() {
       try {
        System.out.println("write");
           FileWriter fw = new FileWriter("c:/WriteData.txt");
           // 将字符串写入文件
           fw.write("Hello World!");
           fw.write("Hello Everyone!");
           fw.close();
       } catch (IOException e) {
       }
   }

   public void DeleteFile() {
       File f = new File("c:/WriteData.txt");
       // 检查文件是否存在,如果存在,直接删除文件
       if (f.exists()) {
           f.delete();
       }
   }

}

com.TaskScheduling.Master.HeartBeatCheck:
package com.TaskScheduling.Master;

import java.util.Date;

public class HeartBeatCheck implements Runnable{
@Override
public void run() {
while(true)
{
Date lastAliveTime = MasterGlobalResource.getLastalivetime();
Date nowTime = new Date();
System.out.println("nowTime="+nowTime.getTime()+"   lastAliveTime="+lastAliveTime.getTime());
//如果超过2秒slave机器没有调用master机器的接口修改Lastalivetime值则认为slave死亡
if(nowTime.getTime()-lastAliveTime.getTime()>2000)
System.out.println("slave has no feedback in 2 second...");
try {
//每1秒钟监测一次
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

}

com.TaskScheduling.Master.JobService:
package com.TaskScheduling.Master;

import com.TaskScheduling.Slave.JobProcess;
import com.caucho.hessian.client.HessianProxyFactory;
/**
 * 任务调度
 *
 */
public class JobService implements Runnable {
private HessianProxyFactory factory = new HessianProxyFactory();
@Override
public void run() {
try {
//添加10个任务到任务队列
Thread.sleep(5000);
for(int i=0;i<10;i++)
{
ZephyrJobWrapper job=new ZephyrJobWrapper();
job.setJobId(String.valueOf(i));
job.setJobName(String.valueOf(i));
job.setJobBeanName("testService");//任务bean名
job.setJobMethodName("getJobInfo");//任务方法名
job.setJobArgs(new Object[]{"hello","xj"+String.valueOf(i)});//方法的参数
MasterGlobalResource.setWaitingJobQueue(job);
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//slave处理任务的接口
JobProcess jobProcess=(JobProcess)factory.create(JobProcess.class, "http://localhost:8080/rmi.test/service/JobProcess");
//轮询任务队列
while(true)
{
System.out.println("size="+MasterGlobalResource.getWaitingJobQueue().size());
for(ZephyrJobWrapper job:MasterGlobalResource.getWaitingJobQueue())
{
//如果任务队列有任务则通过hessian接口交给slave机器执行任务
jobProcess.process(job);
}
   //轮询间隔为一秒钟
Thread.sleep(1000);
}
} catch (Exception e) {
System.out.println(e);
System.out.println("job process failed");
}
}
}

com.TaskScheduling.Master.MasterGlobalResource:
package com.TaskScheduling.Master;

import java.util.Date;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * master机器的全局变量
 *
 */
public  class MasterGlobalResource {
/**
* slave最后心跳时间
*/
private  static Date lastalivetime=new Date();
/**
* 线程池
*/
private static ThreadPoolExecutor                                      executor                 = new ThreadPoolExecutor(
             10,
             10,
             0L,
             TimeUnit.MILLISECONDS,
             new LinkedBlockingQueue<Runnable>(),
             new ThreadPoolExecutor.DiscardPolicy());
/**
 * 任务队列
 */
private static LinkedBlockingQueue<ZephyrJobWrapper>             waitingJobQueue          = new LinkedBlockingQueue<ZephyrJobWrapper>(); 
 
public static ThreadPoolExecutor getExecutor() {
       return executor;
   }
 
public static LinkedBlockingQueue<ZephyrJobWrapper> getWaitingJobQueue()
{
return waitingJobQueue;
}
 
public static void setWaitingJobQueue(ZephyrJobWrapper job)
{
waitingJobQueue.add(job);
}

public static Date getLastalivetime() {
return lastalivetime;
}

public static void setLastalivetime(Date lastalivetime) {
MasterGlobalResource.lastalivetime = lastalivetime;
}

}

com.TaskScheduling.Master.SlaveHeartBeat:
package com.TaskScheduling.Master;

public interface SlaveHeartBeat {
public String check() ;
}

com.TaskScheduling.Master.ZephyrJobWrapper:
package com.TaskScheduling.Master;

import java.io.Serializable;
/**
 * job定义类
 *
 */
public class ZephyrJobWrapper implements Serializable{
private static final long serialVersionUID = 6453296403466572073L;
public String jobId;
public String jobName;
public String getJobId() {
return jobId;
}
public void setJobId(String jobId) {
this.jobId = jobId;
}
public String getJobName() {
return jobName;
}
public void setJobName(String jobName) {
this.jobName = jobName;
}
}

slave相关类:
com.TaskScheduling.Slave.JobProcess:
package com.TaskScheduling.Slave;

import com.TaskScheduling.Master.ZephyrJobWrapper;

public interface JobProcess {
public String process(ZephyrJobWrapper job);

}


com.TaskScheduling.Slave.impl.JobProcessImpl:
package com.TaskScheduling.Slave.impl;

import java.lang.reflect.Method;

import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import com.TaskScheduling.Master.ZephyrJobWrapper;
import com.TaskScheduling.Slave.JobProcess;
/**
 * 处理master分配给slave的任务
 *
 */
public class JobProcessImpl implements JobProcess,ApplicationContextAware{
private ApplicationContext  applicationContext;

@Override
public String process(ZephyrJobWrapper job) {
String result="success";
Object jobBean = applicationContext.getBean(job.getJobBeanName());
        Class<?> clazz = jobBean.getClass();
        Method jobMethod = null;
        Object[] args = null;
        for (Method method : clazz.getMethods()) {
            Class<?>[] paramTypes = method.getParameterTypes();

            if (method.getName().equals(job.getJobMethodName())) {
                Object jobArgs = job.getJobArgs();

                /** 传入Object[]参数时,检查方法名和参数个数 **/
                if (jobArgs != null && jobArgs.getClass().getSimpleName().equals("Object[]")) {
                    args = (Object[]) jobArgs;

                    if (args.length == paramTypes.length) {
                        jobMethod = method;
                        break;
                    }
                }
                /** 不传参或者传入其它类型参数时,只检查方法名 **/
                else {
                    jobMethod = method;
                    break;
                }
            }
        }
        try {
if (jobMethod != null) {
   if (args == null) {
       jobMethod.invoke(jobBean, job.getJobArgs());
   } else {
       jobMethod.invoke(jobBean, args);
   }
} else {
result="failed";
}
} catch (Exception e) {
result="failed";
System.out.println("complete process job "+job.getJobName()+"successful!");
return result;
}

@Override
public void setApplicationContext(ApplicationContext applicationContext)
throws BeansException {
this.applicationContext=applicationContext;
}

}


com.TaskScheduling.Slave.HeartBeat:
package com.TaskScheduling.Slave;


import com.TaskScheduling.Master.SlaveHeartBeat;
import com.caucho.hessian.client.HessianProxyFactory;
/**
 * 每1秒调用master接口修改最后更新时间,用来心跳监测
 *
 */
public class HeartBeat implements Runnable {
private HessianProxyFactory factory                = new HessianProxyFactory();

@Override
public void run() {
while(true)
{
try {
SlaveHeartBeat heatBeat=(SlaveHeartBeat)factory.create(SlaveHeartBeat.class, "http://localhost:8081/service/HeatBeat");
String result=heatBeat.check();
System.out.println(result);
Thread.sleep(1000);
} catch (Exception e) {
System.out.println("slave cannot connect to master...check master run well");
}
}
}
}

com.TaskScheduling.Slave.SlaveAutoRun:
package com.TaskScheduling.Slave;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.http.HttpServlet;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

@SuppressWarnings("serial")
public class SlaveAutoRun extends HttpServlet implements ServletContextListener {
public SlaveGlobalResource slaveGlobalResource;

@Override
public void contextDestroyed(ServletContextEvent arg0) {

}

@SuppressWarnings("static-access")
@Override
public void contextInitialized(ServletContextEvent arg0) {
ApplicationContext app=new ClassPathXmlApplicationContext("classpath*:spring/*.xml");
//心跳检测
slaveGlobalResource.getExecutor().execute((HeartBeat)app.getBean("heartBeat"));
}

}

com.TaskScheduling.Slave.SlaveGlobalResource:
package com.TaskScheduling.Slave;

import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
 * slave的全局变量
 *
 */
public class SlaveGlobalResource {
public static ThreadPoolExecutor executor=new ThreadPoolExecutor( 10,
            10,
            0L,
            TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<Runnable>(),
            new ThreadPoolExecutor.DiscardPolicy()); 
public static ThreadPoolExecutor getExecutor()
{
return executor;
}

}

com.TaskScheduling.Slave.service.TestService:
package com.TaskScheduling.Slave.service;
/**
 * 需要slave处理的任务类
 *
 */
public class TestService {
public void getJobInfo(String str1,String str2)
{
System.out.println(str1+"---------"+str2);
return ;
}

}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
#include #include #include //队列最大长度 #define MAX_QUEUE 1024 //偷懒,就用静态队列了 static int mQueue[MAX_QUEUE]; //队列插入 void InsertData(int **Front, int **Rear) { if (*Rear + 1 == *Front && (*Rear + 1 - MAX_QUEUE != *Front)) { //当队列数据已满,返回 puts("Queue Size Overflow!\n"); return; } else if (*Rear - mQueue > MAX_QUEUE) { //实现的是类似循环队列,但由于是静态线性队列(数组) //而不是用链表来实现的,所以到静态队列(数组)尾部,尾指针自动指向(数组)头部 *Rear = mQueue; } puts("Input Data:"); scanf("%d", *Rear); //输入数据后,尾指针后移 *Rear += 1; } //从头指针删除一个队列中的数据 void DeleteData(int **Front, int **Rear) { if (*Front == *Rear) { //头指针尾指针重合,队列空,不能删除,返回 puts("Queue Empty!\n"); return; } else if (*Front - mQueue > MAX_QUEUE) { //参考 Rear *Front = mQueue; } //从头指针删除一个数据 *Front += 1; } //显示队列数据 void ShowData(int **Front, int **Rear) { int *temp; for (temp=*Front; temp!=*Rear; temp++) { printf("%d --> ", *temp); } puts("\n"); } void usage(void) { puts("1. Insert Data"); puts("2. Delete Data"); puts("3. Show Data"); } int main(int argc, char **argv) { //头指针,尾指针 //队列的一个特性 First in first out FIFO int *pFront, *pRear; int op_code; //初始化队列,头指针和尾指针此时指向的地址相同 pFront = pRear = mQueue; while (1) { usage(); scanf("%d", &op_code); switch (op_code) { case 1: printf("%p\n", pFront); printf("%d\n", *pFront); InsertData(&pFront, &pRear); break; case 2: DeleteData(&pFront, &pRear); break; case 3: ShowData(&pFront, &pRear); break; default: break; } } return 0; }

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值