■1.Quartz方式(Quartz版本:2.2.3)

Quartz的定时任务能力比较强大,它自己就可以实现集群功能。Quartz在实现集群功能时,利用了数据库对任务进行调度,而其使用到的数据库表数据都是自动装填的不用认为管理表数据。我们只需要按照Quartz要求建表即可。所需要建表,Quartz已经帮我们写好了SQL,只需要对照你的数据库找到相应的SQL执行一下即可。

Quartz官网:http://www.quartz-scheduler.org/

从官网上直接下载 Quartz 2.2.3 .tar.gz,解压后【quartz-2.2.3/docs/dbTables】下存放各数据库建表的sql文件。

本实例使用的是postgeresql数据库。所以,使用tables_postgres.sql创建所需要的表。

下面是项目代码

A.文件目录结构

B.各文件内容:pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com</groupId>
	<artifactId>lpwmsbatch</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>

	<name>lpwmsbatch</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.4.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>1.3.2</version>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.postgresql</groupId>
			<artifactId>postgresql</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid</artifactId>
			<version>1.1.8</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.apache.curator/curator-framework -->
		<dependency>
			<groupId>org.apache.curator</groupId>
			<artifactId>curator-framework</artifactId>
			<version>2.12.0</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-quartz</artifactId>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz -->
		<dependency>
			<groupId>org.quartz-scheduler</groupId>
			<artifactId>quartz</artifactId>
			<version>2.2.3</version>
		</dependency>
		<dependency>
			<groupId>org.quartz-scheduler</groupId>
			<artifactId>quartz-jobs</artifactId>
			<version>2.2.3</version>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>

各文件内容:application.properties

# 服务端口
server.port=8080

# Mybatis
spring.profiles.active=dev
mybatis.type-aliases-package=com.infosky.batch.model
mybatis.mapper-locations=classpath*:com/infosky/batch/mapper/*.xml

# 数据源
spring.datasource.url=jdbc:postgresql://xxx.xxx.xxx.xxx:5432/lpaa
spring.datasource.username=test
spring.datasource.password=test
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true

# ↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓Quartz↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
# ============================================================================
# Configure Main Scheduler Properties  
# ============================================================================
# 调度标识名 集群中每一个实例都必须使用相同的名称 
org.quartz.scheduler.instanceName= TestScheduler

# ID设置为自动获取 每一个必须不同
# 1. 当你想生成intanceId的时候可以设置为AUTO
# 2. 当你想从系统属性org.quartz.scheduler.instanceId取值时可以设置为SYS_PROP
org.quartz.scheduler.instanceId= instance_one

# 生成Schudule实体Id的类,只有在属性org.quartz.scheduler.instanceId设置为AUTO时使用,默认的实现org.quartz.scheduler.SimpleInstanceGenerator是基于主机名称和时间戳生成。其他的实现查看具体的文档
# org.quartz.scheduler.instanceIdGenerator.class

# Scheduler线程的名称
# org.quartz.scheduler.threadName

# 指定Scheduler是否以守护线程(服务)运行
# org.quartz.scheduler.makeSchedulerThreadDaemon

# 当调度程序空闲时,在重新查询可用触发器之前,调度程序将等待毫秒的时间数。不建议少于5000ms,而少于1000是不合法的参数
# org.quartz.scheduler.idleWaitTime

# 使用JobStore(比如连接数据库)时Schueduler检测到失去数据库连接后重新尝试连接的毫秒数
# org.quartz.scheduler.doFailureRetryInterval

# 给Scheduler Context、Job、Trigger的JobDataMaps设置属性值的方式
# org.quartz.scheduler.jobFactory.class

# 键值对,保存在Scheduler Context中,比如有这样的配置org.quartz.shceduler.key.MyKey=MyValue,则在Scheduler Context中赋值方式为scheduler.getContext().put(“MyKey”, “MyValue”
# org.quartz.contenxt.key.SOME_KEY

# 事务管理JNDI URL地址。只有当Quartz使用JobStoreCMT和org.quartz.scheduler.wrapJobExecutionInUserTransaction 设置为true时使用
# org.quartz.scheduler.userTransactionURL

# 只有当你在执行一个Job时想使用UserTransaction时设置为true,参考@ExecuteInJTATransaction 注解
# org.quartz.scheduler.wrapJobExecutionInUserTransaction

# 在同一时间运行Scheduler获取trigger的数量。如果设置的数量>1,并且使用JDBC JobStore,则属性org.quartz.jobStore.acquireTriggersWithinLock应设置为true,可以避破坏数据。
# org.quartz.scheduler.batchTriggerAcquisitionMaxCount

# 运行Scheduler在获取和触发tigger的提前的时间。
# org.quartz.scheduler.batchTriggerAcquisitionFireAheadTimeWindow

# 是否跳过版本检测。可以设置系统参数org.terracotta.quartz.skipUpdateCheck=true或者在JAVA命令行使用-D选项。在正式库运行时应设置为true。
org.quartz.scheduler.skipUpdateCheck= true

# ============================================================================
# Configure ThreadPool  
# 线程池配置
# ============================================================================
# 线程池的实现类(一般使用SimpleThreadPool即可满足几乎所有用户的需求)
# Scheduler使用的线程池名称,实现了ThreadPool接口,参考org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.class= org.quartz.simpl.SimpleThreadPool

# 指定线程数,至少为1(无默认值)(一般设置为1-100直接的整数合适) 
org.quartz.threadPool.threadCount= 5

# 设置线程的优先级(最大为java.lang.Thread.MAX_PRIORITY 10,最小为Thread.MIN_PRIORITY 1,默认为5)
org.quartz.threadPool.threadPriority= 5

# ============================================================================
# Configure JobStore  
# JDBCJobStore和JobStoreTX
# JDBCJobStore和JobStoreTX都使用关系数据库来存储Schedule相关的信息。
# JobStoreTX在每次执行任务后都使用commint或者rollback来提交更改。
# 如果在一个标准的独立应用或者在一个没有使用JTA事务管理的应用中使用Quartz,JDBCJobStore是一个不错的选择。
# ============================================================================
# 信息保存时间 默认值60秒 
# 触发器失败后下次触发的时间间隔
org.quartz.jobStore.misfireThreshold= 60000

# 数据保存方式为数据库持久化  
org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX

# 使用的数据库驱动,具体的驱动列表详情如下。一般org.quartz.impl.jdbcjobstore.StdJDBCDelegate可以满足大部分数据库 
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate

# 使用自己的配置文件
# 配置参数可以被设置为true(默认为false),这样可以指导JDBCJobStore,JobDataMaps中的值都是字符串,因此这样可以以名字-值对存储,而不是存储更加复杂的对象(序列化形式BLOB)。从长远来看,这是很安全的,因为避免了将非字符串类序列化为BLOB的类版本问题。
org.quartz.jobStore.useProperties=false

# 数据库别名 随便取
org.quartz.jobStore.dataSource=myDS

# 表的前缀,默认QRTZ_ 
org.quartz.jobStore.tablePrefix=QRTZ_

# 是否加入集群
org.quartz.jobStore.isClustered=true

# 检查集群下的其他调度器实体的事件间隔
# org.quartz.jobStore.clusterCheckinInterval

# 如果值为true,就是告诉Quartz(当使用JobStoreTX或CMT)调用JDBC连接的setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE)方法。这可以防止在高负载、持久事务时锁定超时。
# org.quartz.jobStore.txIsolationLevelSerializable

#============================================================================
# Other Example Delegates
#============================================================================
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.DB2v6Delegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.DB2v7Delegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.DriverDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.HSQLDBDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.MSSQLDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PointbaseDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.StdJDBCDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.WebLogicDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.oracle.OracleDelegate
#org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.oracle.WebLogicOracleDelegate

#============================================================================
# Configure Datasources  
#============================================================================
# 数据库引擎 
# 必须是数据库的JDBC驱动的类名
org.quartz.dataSource.myDS.driver= org.postgresql.Driver

# 数据库连接
org.quartz.dataSource.myDS.URL= jdbc:postgresql://xxx.xxx.xxx.xxx:5432/lpaa
org.quartz.dataSource.myDS.user= test
org.quartz.dataSource.myDS.password= test

# 允许最大连接
org.quartz.dataSource.myDS.maxConnections= 5

# SQL查询字符串,数据源用于检测和替换失败或者故障连接
org.quartz.dataSource.myDS.validationQuery= select 0

# 空闲连接测试的时间(单位秒),只有设置了validationQuery属性,才使能。默认值为50秒
# org.quartz.dataSource.NAME.idleConnectionValidationSeconds

# 是否每一次从数据池冲获取连接时,都要去执行数据库SQL查询,以确保连接有效。如果为false,那么在check-in时验证。默认值为false
# org.quartz.dataSource.NAME.validateOnCheckout

# 丢弃连接的超时时间。若值为0,则禁止这个特性。默认值为0
# org.quartz.dataSource.NAME.discardIdleConnectionsSeconds

# 应用服务器管理的数据源的JNDI的URL
# org.quartz.dataSource.NAME.jndiURL

#============================================================================
# Configure Plugins 
#============================================================================

#org.quartz.plugin.shutdownHook.class: org.quartz.plugins.management.ShutdownHookPlugin
#org.quartz.plugin.shutdownHook.cleanShutdown: true
#org.quartz.plugin.triggHistory.class: org.quartz.plugins.history.LoggingJobHistoryPlugin
#↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑Quartz↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑↑

各文件内容:SpringBootStartApplication.java

package com.infosky.batch;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@MapperScan("com.infosky.batch.dao")
public class SpringBootStartApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringBootStartApplication.class, args);
	}
}

各文件内容:AutowiringSpringBeanJobFactory.java

package com.infosky.batch.quartz;

import org.quartz.spi.TriggerFiredBundle;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.scheduling.quartz.SpringBeanJobFactory;

public final class AutowiringSpringBeanJobFactory extends SpringBeanJobFactory implements ApplicationContextAware {

	private transient AutowireCapableBeanFactory beanFactory;

	@Override
	public void setApplicationContext(final ApplicationContext context) {
		beanFactory = context.getAutowireCapableBeanFactory();
	}

	@Override
	protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {
		final Object job = super.createJobInstance(bundle);
		beanFactory.autowireBean(job);
		return job;
	}
}

各文件内容:CheckStatusTask.java

package com.infosky.batch.quartz;

import org.quartz.*;
import org.springframework.stereotype.Component;

@PersistJobDataAfterExecution
@DisallowConcurrentExecution
@Component
public class CheckStatusTask implements Job {
	public void execute(JobExecutionContext context) throws JobExecutionException {
		// 定时任务逻辑
		System.out.println("^^^^^^^^^^^^^");
	}

}

各文件内容:QuartzConfig.java

package com.infosky.batch.quartz;

import org.quartz.spi.JobFactory;
import org.springframework.beans.factory.config.PropertiesFactoryBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import java.util.Properties;

/**
 * 配置定时任务
 *
 */
@Configuration
public class QuartzConfig {
	public static final String QUARTZ_PROPERTIES_PATH = "/application.properties";

	@Bean
	public JobFactory jobFactory(ApplicationContext applicationContext) {
		AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory();
		jobFactory.setApplicationContext(applicationContext);
		return jobFactory;
	}

	@Bean
	public SchedulerFactoryBean schedulerFactoryBean(JobFactory jobFactory) {
		SchedulerFactoryBean schedulerFactoryBean = new SchedulerFactoryBean();
		schedulerFactoryBean.setJobFactory(jobFactory);
		schedulerFactoryBean.setStartupDelay(20);
		// 用于quartz集群,加载quartz数据源配置
		schedulerFactoryBean.setQuartzProperties(quartzProperties());
		return schedulerFactoryBean;
	}

	public Properties quartzProperties() {
		PropertiesFactoryBean factoryBean = new PropertiesFactoryBean();
		factoryBean.setLocation(new ClassPathResource(QUARTZ_PROPERTIES_PATH));
		try {
			factoryBean.afterPropertiesSet();
			return factoryBean.getObject();
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
}

各文件内容:QuartzScheduler.java

package com.infosky.batch.quartz;

import static org.quartz.CronScheduleBuilder.cronSchedule;
import javax.annotation.PostConstruct;
import org.quartz.JobBuilder;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;
import org.springframework.stereotype.Component;

/**
 * 定时任务调度器
 */
@Component
public class QuartzScheduler {
	@SuppressWarnings("SpringJavaAutowiringInspection")
	@Autowired
	private SchedulerFactoryBean schedulerFactoryBean;

	@PostConstruct
	public void init() throws SchedulerException {
		scheduleJobs();
	}

	public void scheduleJobs() throws SchedulerException {
		System.out.println("=======任务初始化========");
		Scheduler scheduler = schedulerFactoryBean.getScheduler();
		// 需要传递数据,就是使用JobDataMa
//		 JobDataMap jobDataMap = new JobDataMap();
//		 jobDataMap.put("jobArg", "world");
		// CheckStatusTask.class 是需要执行定时任务的类名
		JobDetail jobDetail = JobBuilder.newJob(CheckStatusTask.class)//.setJobData(jobDataMap)
				// .setJobData(jobDataMap)
				.withDescription("CheckStatusTask").withIdentity("job-CheckStatus", "demo-group").build();
		// InsertEvaluateTask.class 是需要执行定时任务的类名
		// JobDetail jobDetail2 = JobBuilder.newJob(InsertEvaluateTask.class)
		// // .setJobData(jobDataMap)
		// .withDescription("InsertEvaluateTask")
		// .withIdentity("job-InsertEvaluate", "demo-group")
		// .build();

		Trigger trigger = TriggerBuilder.newTrigger().forJob(jobDetail).withSchedule(cronSchedule("*/1 * * * * ? "))
				.build();

		// Trigger trigger2 = TriggerBuilder.newTrigger()
		// .forJob(jobDetail2)
		// .withSchedule(cronSchedule("0 0/1 * * * ? "))
		// .build();

		try {
			if (!scheduler.checkExists(JobKey.jobKey("job-CheckStatus", "demo-group"))) {
				scheduler.scheduleJob(jobDetail, trigger);
			}
			// if(!scheduler.checkExists(JobKey.jobKey("job-InsertEvaluate","demo-group"))){
			// scheduler.scheduleJob(jobDetail2,trigger2);
			// }
			scheduler.start();
			System.out.println("=======任务初始化完成========");
		} catch (SchedulerException e) {
			e.printStackTrace();
		}
	}
}

●注意:利用数据库这种方式当程序意外终止或者需要修改定时任务时(比如删除一些定时任务),重新启动时有可能因为DB表数据与定时任务不整合可能出现启动异常异常,这时只需要删除Quartz对应的数据库表重新启动即可。

数据库对应表

qrtz_fired_triggers
qrtz_paused_trigger_grps
qrtz_scheduler_state
qrtz_locks
qrtz_simple_triggers
qrtz_cron_triggers
qrtz_simprop_triggers
qrtz_blob_triggers
qrtz_triggers
qrtz_job_details
qrtz_calendars

■zookeeper实现分布式锁方式

A.文件目录结构

B.各文件内容:pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.infosky.batch</groupId>
	<artifactId>lpwmsbatch</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>

	<name>lpwmsbatch</name>
	<description>Demo project for Spring Boot</description>

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.4.RELEASE</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-data-jpa</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>1.3.2</version>
		</dependency>
		<dependency>
			<groupId>mysql</groupId>
			<artifactId>mysql-connector-java</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.postgresql</groupId>
			<artifactId>postgresql</artifactId>
			<scope>runtime</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>com.alibaba</groupId>
			<artifactId>druid</artifactId>
			<version>1.1.8</version>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.apache.curator/curator-framework -->
		<dependency>
			<groupId>org.apache.curator</groupId>
			<artifactId>curator-framework</artifactId>
			<version>2.12.0</version>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-quartz</artifactId>
		</dependency>
		<!-- https://mvnrepository.com/artifact/org.quartz-scheduler/quartz -->
		<dependency>
			<groupId>org.quartz-scheduler</groupId>
			<artifactId>quartz</artifactId>
			<version>2.2.3</version>
		</dependency>
		<dependency>
			<groupId>org.quartz-scheduler</groupId>
			<artifactId>quartz-jobs</artifactId>
			<version>2.2.3</version>
		</dependency>
	</dependencies>

	<build>
		<plugins>
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
		</plugins>
	</build>
</project>

各文件内容:TaskService.java

package task;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class TaskService {

	// 每分钟启动
	@Scheduled(cron = "0 0/1 * * * ?")
	public void oneMinuteJob(){
		System.out.println("now time:" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
	}
}

各文件内容:SpringBootStartApplication.java

package com.infosky.batch;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@MapperScan("com.infosky.batch.dao")
@EnableScheduling
public class SpringBootStartApplication {

	public static void main(String[] args) {
		SpringApplication.run(SpringBootStartApplication.class, args);
	}
}

各文件内容:ZookeeperUtils.java

package com.infosky.batch.utils;

import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;

public class ZookeeperUtils {

	/**
	 * 创建节点。创建成功即获得执行权。
	 * @param strNote
	 * @throws Exception
	 */
	public static void createNote(String strNote) throws Exception {
		// 获取连接
		CuratorFramework curatorFramework = CuratorFrameworkFactory.builder().connectString("172.22.70.45:2181")
				.sessionTimeoutMs(4000).retryPolicy(new ExponentialBackoffRetry(1000, 3)).namespace("curator").build();

		curatorFramework.start();
		try{
			// 获取节点值
			byte[] valNote = curatorFramework.getData().forPath("/taskLock");
			// 节点存在时
			if(valNote != null && valNote.length > 0){
				// 获取节点值
				String strVal = new String(valNote);
				// 节点保存时间
				long logVal = Long.parseLong(strVal);
				// 当前时间
				long logCurrent = DateUtils.getDateTime();
				
				// 节点超过存活时间,删除节点
				if(logCurrent - logVal > 1000*60*60){
					curatorFramework.delete().forPath("/taskLock");
				}
			}
		}catch(Exception e){}
		
		// 创建节点
		curatorFramework.create().withMode(CreateMode.PERSISTENT).forPath("/taskLock", String.valueOf(DateUtils.getDateTime()).getBytes());
	}
}

各文件内容:测试代码:TTT.java

package com.infosky.batch.utils;

import java.util.Date;

public class TTT {

	public static void main(String[] args) {
		try {
			ZookeeperUtils.createNote("");
			System.out.println("$$$$$$$$$$$$$$$$$$$$$$$$$$$$抢到锁");
			System.out.println(new Date());
		} catch (Exception e) {
			System.out.println("############################未抢到锁");
		}

	}

}

各文件内容:DateUtils.java

package com.infosky.batch.utils;

public class DateUtils {

	public static final String JAVA_DATETIME_FORMATTER_24 = "yyyy-MM-dd HH:mm:ss";
	
	/**
	 * 获取当前时间
	 * @return
	 */
	public static long getDateTime(){
		return System.currentTimeMillis();
	}
}

 

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐