@Scheduled定时任务搭配Redis防止多实例定时重复调用

news2024/11/16 19:07:02

有个Redis安装使用教程,可视化界面,有需要的话,可以打开这个链接去看一下

https://blog.csdn.net/weixin_45507672/article/details/105973279

创建个maven项目,在pom.xml文件加上以下依赖

<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
   <groupId>org.springframework.boot</groupId>
   <artifactId>spring-boot-starter-web</artifactId>
</dependency>

以下是Redis的配置文件 

## redis所在的服务器IP
spring.redis.host=127.0.0.1
## 端口
spring.redis.port=6379
## 密码,我这里没有设置,所以不填
spring.redis.password=
## 设置最大连接数,0为无限
spring.redis.pool.max-active=8
## 选择哪个Redis库,可忽略,默认是0
spring.redis.database=1

 

接着然后是创建Redis配置类

package com.example.schedulingtasks.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

@Configuration
public class RedisConfig {

  @Bean
  @SuppressWarnings("all")
  public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory) {
      RedisTemplate<String, Object> template = new RedisTemplate<String, Object>();
      template.setConnectionFactory(factory);
      Jackson2JsonRedisSerializer jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer(Object.class);
      ObjectMapper om = new ObjectMapper();
      om.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
      om.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
      jackson2JsonRedisSerializer.setObjectMapper(om);
      StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();

      // key采用String的序列化方式
      template.setKeySerializer(stringRedisSerializer);
      // hash的key也采用String的序列化方式
      template.setHashKeySerializer(stringRedisSerializer);
      // value序列化方式采用jackson
      template.setValueSerializer(jackson2JsonRedisSerializer);
      // hash的value序列化方式采用jackson
      template.setHashValueSerializer(jackson2JsonRedisSerializer);
      template.afterPropertiesSet();

      return template;
  }


}

接着创建一个定时任务Bean

/*
 * Copyright 2012-2015 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *	  https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.example.schedulingtasks;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import net.javacrumbs.shedlock.spring.annotation.SchedulerLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class ScheduledTasks {

	private static final Logger log = LoggerFactory.getLogger(ScheduledTasks.class);

	private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");

	private static int setnx=0;

	@Autowired
	private RedisTemplate<String,String> redisTemplate;

	ExecutorService executorService = Executors.newCachedThreadPool();
	@Scheduled(cron = "0/20 * * * * ?")
	public void reportCurrentTimeOne() throws InterruptedException {
//		log.info("进来方法1了 {}", dateFormat.format(new Date()));
		Boolean status1 = redisTemplate.opsForValue().setIfAbsent("status", "1");
		if (status1){
			String status111 = redisTemplate.opsForValue().get("status");
			log.info("The time1 is do {},{}", dateFormat.format(new Date()),status111);
			for (int i = 0; i < 10000; i++) {
				redisTemplate.opsForValue().get("a");
			}

		} else {
			String status = redisTemplate.opsForValue().get("status");
			if (status.equals("3")){
				log.info("(方法1)有其它定时器已经在执行 {}",dateFormat.format(new Date()));

			}else {
				Boolean status11 = redisTemplate.delete("status");
				log.info("方法1:delete{}",status11);
				log.info("(方法1)有其它定时器已经在执行 {}",dateFormat.format(new Date()));
			}
		}
	}

	@Scheduled(cron = "0/20 * * * * ?")
	public void reportCurrentTimeTwo() throws InterruptedException {
//		log.info("进来方法2了 {}", dateFormat.format(new Date()));
		Boolean status2 = redisTemplate.opsForValue().setIfAbsent("status", "2");
		if (status2) {
			String status222 = redisTemplate.opsForValue().get("status");
			log.info("The time2 is do {},{}", dateFormat.format(new Date()),status222);
			for (int i = 0; i < 10000; i++) {
				redisTemplate.opsForValue().get("a");
			}
		} else {
			String status = redisTemplate.opsForValue().get("status");
			if (status.equals("1")){
				log.info("(方法2)有其它定时器已经在执行 {}",dateFormat.format(new Date()));

			}else {
				Boolean status22 = redisTemplate.delete("status");
				log.info("方法2:delete{}",status22);
				log.info("(方法2)有其它定时器已经在执行 {}",dateFormat.format(new Date()));
			}
		}
	}
	@Scheduled(cron = "0/20 * * * * ?")
	public void reportCurrentTimeThree() throws InterruptedException {
//		log.info("进来方法2了 {}", dateFormat.format(new Date()));
		Boolean status3 = redisTemplate.opsForValue().setIfAbsent("status", "3");
		if (status3) {
			String status333 = redisTemplate.opsForValue().get("status");
			log.info("The time3 is do {},{}", dateFormat.format(new Date()),status333);
			for (int i = 0; i < 10000; i++) {
				redisTemplate.opsForValue().get("a");
			}
		} else {
			String status = redisTemplate.opsForValue().get("status");
			if (status.equals("2")){
				log.info("(方法3)有其它定时器已经在执行 {}",dateFormat.format(new Date()));

			}else{
				Boolean status33 = redisTemplate.delete("status");
				log.info("方法3:delete{}",status33);
				log.info("(方法3)有其它定时器已经在执行 {}",dateFormat.format(new Date()));
			}
		}
	}
	//个人觉得在多线程下,fixedRate和fixedDelay是没有啥区别的
//	@Scheduled(fixedDelay = 5000)
//	public void runfixedDelay() {
//		System.out.println("fixedDelay定时任务开始了---------------------"+new Date());
//		for (int i = 0; i <= 10; i++) {
//			executorService.execute(new SubThread(i));
//		}
//	}

//	@Scheduled(fixedRate = 5000)
//	public void runfixedRate() {
//		System.out.println("fixedRate定时任务开始了---------------------"+new Date());
//		for (int i = 0; i <= 10; i++) {
//			executorService.execute(new SubThread(i));
//		}
//	}

//	@Scheduled(fixedRate = 5000)
//	public void runfixedRatesingle() throws InterruptedException {
//		//加入逻辑执行时间超过定时器设定时间,那么会在逻辑执行完毕后的第一时间继续调用
//		//也就是第一次执行时间是12:00:04  逻辑执行需要8秒,就是12:00:12执行完成
//		//那么下一次定时器执行方法的时间就是12:00:12
//		System.out.println("runfixedRatesingle定时任务开始了---------------------" + new Date());
//		Thread.sleep(6*1000);
//		System.out.println("执行完毕" + new Date());
//	}

//	@Scheduled(fixedDelay = 5000)
//	public void runfixedDelaysingle() throws InterruptedException {
//		//加入逻辑执行时间超过定时器设定时间,那么会在逻辑执行完毕后需要等待定时器设定的时间后继续调用
//		//也就是第一次执行时间是12:00:04  逻辑执行需要8秒,就是12:00:12执行完成
//		//那么下一次定时器执行方法的时间就是12:00:20
//		System.out.println("runfixedDelayingle定时任务开始了---------------------" + new Date());
//		Thread.sleep(8*1000);
//		System.out.println("执行完毕" + new Date());
//	}

	class SubThread extends Thread{
		private final int i;
		public SubThread(int i){
			this.i=i;
		}
		@Override
		public void run() {
			try {
				//要是执行方法的时间不够,定时任务就算启动了,也要等上一个任务执行完毕后才会执行
				Thread.sleep(8000);
			} catch (InterruptedException e) {
				throw new RuntimeException(e);
			}
			System.out.println("线程名称"+Thread.currentThread().getName()+"当前的任务"+i+new Date());
		}
	}

//“30 * * * * ?” 每半分钟触发任务
//“30 10 * * * ?” 每小时的10分30秒触发任务
//“30 10 1 * * ?” 每天1点10分30秒触发任务
//“30 10 1 20 * ?” 每月20号1点10分30秒触发任务
//“30 10 1 20 10 ? *” 每年10月20号1点10分30秒触发任务
//“30 10 1 20 10 ? 2011” 2011年10月20号1点10分30秒触发任务
//“30 10 1 ? 10 * 2011” 2011年10月每天1点10分30秒触发任务
//“30 10 1 ? 10 SUN 2011” 2011年10月每周日1点10分30秒触发任务
//“15,30,45 * * * * ?” 每15秒,30秒,45秒时触发任务
//“15-45 * * * * ?” 15到45秒内,每秒都触发任务
//“15/5 * * * * ?” 每分钟的每15秒开始触发,每隔5秒触发一次
//“15-30/5 * * * * ?” 每分钟的15秒到30秒之间开始触发,每隔5秒触发一次
//“0 0/3 * * * ?” 每小时的第0分0秒开始,每三分钟触发一次
//“0 15 10 ? * MON-FRI” 星期一到星期五的10点15分0秒触发任务
//“0 15 10 L * ?” 每个月最后一天的10点15分0秒触发任务
//“0 15 10 LW * ?” 每个月最后一个工作日的10点15分0秒触发任务
//“0 15 10 ? * 5L” 每个月最后一个星期四的10点15分0秒触发任务
//“0 15 10 ? * 5#3” 每个月第三周的星期四的10点15分0秒触发任务

//	Timer
//	ExecutorService
//	Spring @Scheduled
//  quartz
//	xxljob
//  elastic-job
}

 最后在启动类上加上@EnableScheduling注解

 然后就可以启动运行,从控制台可以看到三个相同的定时任务在时间段内是交换执行的。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/70749.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

4EVERLAND专用网关公告,免费体验

我们很高兴地宣布发布 4EVERLAND 专用 IPFS 网关&#xff01;与 4EVERLAND 公共网关一起&#xff0c;4EVERLAND 专用网关将为全世界的开发者和用户提供更快、更稳定地访问更能体现其品牌形象的 IPFS 内容。 专用网关的好处&#xff1a; 全球分布的边缘节点提供全球加速无速率…

[附源码]计算机毕业设计快转二手品牌包在线交易系统Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Spring Boot 入门到精通(二)

文章目录五、SpringBoot整合MyBatis5.1 mapper 配置5.2 mapper映射配置&#xff1a;配置文件方式5.3 注解配置方式六. 自定义部分SpringMvc配置。6.1 SpringBoot整合日期转换器6.1.1 配置原理6.1.2 日期转换器整合6.2 SpringBoot整合拦截器七. Spring Boot 自定义日志配置&…

C++11特性-类的改进

1.构造函数 1.委托构造函数&#xff1a;允许同一个类的构造函数调用其他构造函数&#xff0c;简化变量初始化 class BB { public:BB() {}BB(int max) {this->m_max max > 0 ? max : 100;cout << "max " << this->m_max << endl;}BB(i…

【ATF】bootloader与安全相关启动分析

这个文章的内容不只是指的ATF启动这个部分&#xff0c;其实ATF是TF-A&#xff0c;这个是一个启动框架&#xff0c;所以今天我们来看看bootloader这部分的启动代码。后续继续补充&#xff01;&#xff01;&#xff01; 第一部分参考的内容来自&#xff1a;https://mp.weixin.qq…

美食餐厅网站毕业设计,餐厅座位预定系统设计与实现,毕业设计怎么写论文毕设源码开题报告需求分析怎么做

项目背景和意义 目的&#xff1a;本课题主要目标是设计并能够实现一个基于java的公司企业网站&#xff0c;整体基于B/S架构&#xff0c;技术上使用基于java的springboot框架来实现&#xff1b;通过后台添加公司资讯、公司产品、公司产品案例、查看注册用户、查看留言等&#xf…

【无人机分配】一种无人机实时最优任务分配模型附matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …

解决Android嵌套H5,自定义控制页面能否实现下拉刷新功能

目录使用场景问题描述思路分析解决方案结语使用场景 关于Android嵌套H5页面使用下拉刷新功能的问题&#xff1a;当我们在Android中使用第三方框架SmartRefreshLayout实现App的下拉刷新功能时&#xff0c;如果H5页面有部分功能设计到上下滑动的话&#xff0c;就会引起“误触”下…

Jenkins Kubernetes 应用部署与容器构建

Jenkins & Kubernetes 应用部署与容器构建 文章目录Jenkins & Kubernetes 应用部署与容器构建1. 前言2. Jenkins 配置 kubernetes credentials3. Jenkins 插件3.1 安装 Kubernets Plugin3.2 安装 Docker Plugin3.3 安装 Git Plugin4. Jenkins 连接 minikube 集群5. 配置…

MQ高级(一)消息可靠性

消息从生产者发送到exchange&#xff0c;再到queue&#xff0c;再到消费者&#xff0c;有哪些导致消息丢失的可能性&#xff1f; &#xff08;1&#xff09;发送时丢失&#xff1a; 1️⃣生产者发送的消息未送达exchange 2️⃣消息到达exchange后未到达queue &#xff08;2&…

【物理应用】基于傅里叶伽辽金谱法二维纳维-斯托克斯附matlab代码

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;修心和技术同步精进&#xff0c;matlab项目合作可私信。 &#x1f34e;个人主页&#xff1a;Matlab科研工作室 &#x1f34a;个人信条&#xff1a;格物致知。 更多Matlab仿真内容点击&#x1f447; 智能优化算法 …

[附源码]计算机毕业设计教育企业网站Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

当我们说大数据Hadoop,究竟在说什么?

前言 提到大数据&#xff0c;大抵逃不过两个问题&#xff0c;一个是海量的数据该如何存储&#xff0c;另外一个就是那么多数据该如何进行查询计算呢。好在这些问题前人都有了解决方案&#xff0c;而Hadoop就是其中的佼佼者&#xff0c;是目前市面上最流行的一个大数据软件&…

【精品】【含数据+代码+论文链接】交通流预测代码集合

前言 交通流预测代码集合 一、T-GCN 一种用于流量预测的时间图卷积网络 准确、实时的交通预测在智能交通系统中起着重要作用&#xff0c;对城市交通规划、交通管理和交通控制具有重要意义。然而&#xff0c;交通预测一直被认为是一个开放的科学问题&#xff0c;受限于城市…

Python完成期末大作业:简易计算器【案例分享】

嗨害大家好鸭&#xff01;我是小熊猫~ 好像好久都没给大家更新啦&#xff01; 这次来给大家做一个我弟刚刚做完的期末考试大作业 做一个简易计算器 要求&#xff1a; 1.要有加减乘除四个方法的编写2.提交的代码悟编译错误3.代码需要有基础的健壮性判断 源码、资料电子书点击…

汉明码(海明码)解析

文章目录前言启发汉明码介绍怎么实现汉明码?怎么实现更高模块的汉明码?为什么校验位一定是2的n次方?用更简洁的方式理解汉明码前言 相信使用过光盘的读者都会有这样一种经历,如果不小心刮花了盘面,大部分情况下,把它放进DVD机器却仍然可以播放视频,这是为什么呢? 因为光盘…

Tomcat打破双亲委派机制实现各应用程序的类库相互隔离原理与实现demo

1、实现原理 以Tomcat类加载为例&#xff0c;Tomcat 如果使用默认的双亲委派类加载机制行不行&#xff1f; 我们思考一下&#xff1a;Tomcat是个web容器&#xff0c; 那么它要解决什么问题&#xff1a; 1. 一个web容器可能需要部署两个应用程序&#xff0c;不同的应用程序可能会…

C++对const引用的特殊处理、为什么函数形参的引用建议加上const?只是为了防止值被修改吗?

前言&#xff1a;我们知道普通变量、指针、函数形参&#xff0c;加上const修饰表示不可改变&#xff0c;但是引用前面加上const就有特别之处了 目录 const日常使用 const引用的特别处理 const引用创建临时变量规则 引用形参声明为const的三个理由 const日常使用 我们知道如…

resnet(2)------看看卷积

文章目录1 . 人脑是怎么认识到物体的2. 卷积3. 卷积核1 . 人脑是怎么认识到物体的 在谈卷积之前&#xff0c;我们先来了解一下人是怎么认识物体的。 人脑是个非常复杂的结构&#xff0c;是由无数个神经元连接起来&#xff0c;每个神经元都有自己负责记忆的东西。当人眼看到物体…

关于自增约束auto_increment需要注意的地方,mysql8版本的报错

目录一&#xff0c;自增约束auto_increment需要注意的地方附&#xff1a;就算插入数据失败&#xff0c;也进行自增&#xff1a;二&#xff0c;自增约束auto_increment在MySQL8版本的报错&#xff1a;一&#xff0c;自增约束auto_increment需要注意的地方 1 创建数据库表class&…