集群环境下的单例任务调度基类

最近为公司框架提供了基于ID的单例的任务调度基类,用于集群的环境下,一个任务同一时间只能被调度一次。

 

接口声明
继承该基类的任务需要覆盖两个抽象函数:
        protected abstract String getServiceID();//服务ID,与数据库中的和timeservice.xml中的要配置相同       
        protected abstract void doTask();//执行任务,需覆盖的业务方法

 

实现机理

每个任务要有唯一的ServiceId,该任务在t_s_sys_timeservice 中有一条记录,同时有一个state记录着状态信息,state为0表示未占用,state为1表示已占用。

设计上还要考虑处理异常的情况,通过引入一个超时时间,如果已经超时,则认为改状态为未被占用

 

关键代码

 

package com.itown.framework.schedule;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.apache.log4j.Logger;

import com.itown.framework.exception.ServiceInvokeException;
import com.itown.framework.impl.ThreadContext;
import com.itown.framework.persistence.DataSourceFactory;
import com.itown.framework.persistence.ParamsMaker;
import com.itown.framework.persistence.SingleDBHelper;
import com.itown.framework.transaction.FrameworkTransaction;
import com.itown.framework.transaction.JDBCTransaction;

/**
*	timeout_interval用来设定超时时间,单位是秒,极端情况state可能为1,当达到超时时间时,再次执行,要求超时时间一定要大于task的执行时间
*/
public abstract class SingletonTimeService extends TimeService {
	
	private static final Logger	logger	= Logger.getLogger(SingletonTimeService.class);
	
	private String selectSql = "select * from t_s_sys_timeservice where (id = ? and state = '0') or (id = ? and sysdate > update_date + timeout_interval/86400 )"; 
	private String updateLockSql = "update t_s_sys_timeservice set update_date = sysdate,state = 1 where (id = ? and state = '0') or (id = ? and sysdate > update_date + timeout_interval/86400 )"; 
	private String updateUnlockSql = "update t_s_sys_timeservice set update_date = sysdate,state = '1' where id = ?"; 
	
	public void doTimeService() {
        String funcName = "SingletonTimeService.doTimeService";
        logger.info(funcName + " begin time:" + System.currentTimeMillis());
		ThreadContext ctx = ThreadContext.getThreadContext();
		FrameworkTransaction _tr = null;
		Connection _conn = null;
		try {
			_conn = DataSourceFactory.getDefaultConnection();			
			_tr = new JDBCTransaction(_conn);
			_tr.begin();			

			//争任务,此处无法采用框架提供的封装
			PreparedStatement ps = null;
			ResultSet rs = null;
			try {
				logger.info(funcName + " selectSql:" + selectSql);
				logger.info(funcName + " id:" + getServiceID());
				ps = _conn.prepareStatement(selectSql);
				ps.setString(1, getServiceID());
				ps.setString(2, getServiceID());
				rs = ps.executeQuery();
			} catch (SQLException ex) {
				logger.error(ex);
				throw ex;
			}
			int result =0;//result > 0 表示抢到任务
			if(rs.next()){
				SingleDBHelper helper = new SingleDBHelper(_conn);				
				//锁定任务
				try{
					logger.info(funcName + " updateLockSql:" + updateLockSql);
					logger.info(funcName + " id:" + getServiceID());
					result=helper.executeUpdate(updateLockSql,ParamsMaker.makeParams(getServiceID()));
					_tr.commit();
					
				}catch(Exception e){
					logger.error(e);
				}
				
				//执行任务
				try{
					_tr.begin();
					logger.info(funcName + " 开始执行timeservice(id="+getServiceID()+")任务...");
					if(result>0){
						doTask();
					}
					logger.info(funcName + " 结束执行timeservice(id="+getServiceID()+")任务。");
				}catch(Throwable e){
					logger.error(e);
					throw e;
					
				}				

				//解锁
				//注释此timeservice解锁业务,超时会自动满足timeservice执行条件;

				try{
					logger.info(funcName + " updateUnlockSql:" + updateUnlockSql);
					logger.info(funcName + " id:" + getServiceID());
					if(result>0){
						helper.executeUpdate(updateUnlockSql,ParamsMaker.makeParams(getServiceID()));
					}
				}catch(Exception e){
					logger.error(e);
				}
				
			}
			
			//事务相关操作
			_tr.commit();							
		} catch (Throwable ex) {
			if (_tr != null) {
				try {
					_tr.rollback();
				} catch (Exception ex1) {
					logger.error(ex1);
				}
			}
			throw new ServiceInvokeException("调度异常", ex);
		} finally {
			ctx.runShieldStatements();
			DataSourceFactory.release(_conn);
		}
	}

	protected abstract String getServiceID();
	
	protected abstract void doTask();
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值