Java调度任务如何使用分布式锁保证相同任务在一个周期里只执行一次?

简介: 【10月更文挑战第29天】Java调度任务如何使用分布式锁保证相同任务在一个周期里只执行一次?

在Java中,使用分布式锁可以确保在多个实例或服务器之间,相同任务在一个周期内只执行一次。以下是实现这一功能的步骤和示例代码:

步骤

  1. 选择分布式锁的实现:可以使用Redis、Zookeeper等来实现分布式锁。
  2. 获取锁:在任务开始执行之前尝试获取锁。如果成功获取到锁,则继续执行任务;如果没有获取到锁,则跳过执行。
  3. 释放锁:任务执行完毕后,释放锁,以便其他实例可以获取锁并执行任务。

示例代码(使用Redis作为分布式锁)

首先,添加Redis客户端依赖到你的项目中(例如使用Jedis):

<dependency>
    <groupId>redis.clients</groupId>
    <artifactId>jedis</artifactId>
    <version>3.6.0</version>
</dependency>
AI 代码解读

然后,创建一个使用Redis分布式锁的任务调度器:

import redis.clients.jedis.Jedis;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class DistributedTaskScheduler {
   
    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
    private final Jedis jedis = new Jedis("localhost", 6379); // 连接到Redis服务器

    public void start() {
   
        final Runnable task = () -> {
   
            String lockKey = "taskLock";
            long acquireTimeout = 5000; // 获取锁的超时时间(毫秒)
            long lockExpiry = 60000; // 锁的过期时间(毫秒)

            // 尝试获取锁
            if (acquireLock(lockKey, acquireTimeout, lockExpiry)) {
   
                try {
   
                    // 执行任务逻辑
                    System.out.println("Executing task at " + System.currentTimeMillis());
                } finally {
   
                    // 释放锁
                    releaseLock(lockKey);
                }
            } else {
   
                System.out.println("Failed to acquire lock, skipping task execution");
            }
        };
        // 每分钟检查一次是否需要执行任务
        scheduler.scheduleAtFixedRate(task, 0, 1, TimeUnit.MINUTES);
    }

    private boolean acquireLock(String lockKey, long acquireTimeout, long lockExpiry) {
   
        long end = System.currentTimeMillis() + acquireTimeout;
        while (System.currentTimeMillis() < end) {
   
            if (jedis.setnx(lockKey, "locked") == 1) {
    // 尝试设置锁
                jedis.expire(lockKey, (int) (lockExpiry / 1000)); // 设置锁的过期时间
                return true;
            }
            try {
   
                Thread.sleep(100); // 等待一段时间后重试
            } catch (InterruptedException e) {
   
                Thread.currentThread().interrupt();
            }
        }
        return false;
    }

    private void releaseLock(String lockKey) {
   
        jedis.del(lockKey); // 删除锁
    }

    public static void main(String[] args) {
   
        DistributedTaskScheduler scheduler = new DistributedTaskScheduler();
        scheduler.start();
    }
}
AI 代码解读

在这个例子中,我们使用了Redis来存储锁的状态。acquireLock方法尝试获取锁,并在成功获取后设置一个过期时间,以防止死锁的情况发生。releaseLock方法用于释放锁。通过这种方式,我们可以确保在多个实例中,同一任务在一个周期内只被执行一次。

目录
相关文章
在Java中使用Seata框架实现分布式事务的详细步骤
通过以上步骤,利用 Seata 框架可以实现较为简单的分布式事务处理。在实际应用中,还需要根据具体业务需求进行更详细的配置和处理。同时,要注意处理各种异常情况,以确保分布式事务的正确执行。
在Java中实现分布式事务的常用框架和方法
总之,选择合适的分布式事务框架和方法需要综合考虑业务需求、性能、复杂度等因素。不同的框架和方法都有其特点和适用场景,需要根据具体情况进行评估和选择。同时,随着技术的不断发展,分布式事务的解决方案也在不断更新和完善,以更好地满足业务的需求。你还可以进一步深入研究和了解这些框架和方法,以便在实际应用中更好地实现分布式事务管理。
常见的分布式定时任务调度框架
分布式定时任务调度框架用于在分布式系统中管理和调度定时任务,确保任务按预定时间和频率执行。其核心概念包括Job(任务)、Trigger(触发器)、Executor(执行器)和Scheduler(调度器)。这类框架应具备任务管理、任务监控、良好的可扩展性和高可用性等功能。常用的Java生态中的分布式任务调度框架有Quartz Scheduler、ElasticJob和XXL-JOB。
661 66
Java线程调度揭秘:从算法到策略,让你面试稳赢!
在社招面试中,关于线程调度和同步的相关问题常常让人感到棘手。今天,我们将深入解析Java中的线程调度算法、调度策略,探讨线程调度器、时间分片的工作原理,并带你了解常见的线程同步方法。让我们一起破解这些面试难题,提升你的Java并发编程技能!
72 16
|
28天前
|
Java中的分布式缓存与Memcached集成实战
通过在Java项目中集成Memcached,可以显著提升系统的性能和响应速度。合理的缓存策略、分布式架构设计和异常处理机制是实现高效缓存的关键。希望本文提供的实战示例和优化建议能够帮助开发者更好地应用Memcached,实现高性能的分布式缓存解决方案。
39 9
体验用分布式数据库突破资源瓶颈,完成任务领智能台灯!
体验用分布式数据库突破资源瓶颈,完成任务领智能台灯!
基于Java的Hadoop文件处理系统:高效分布式数据解析与存储
本文介绍了如何借鉴Hadoop的设计思想,使用Java实现其核心功能MapReduce,解决海量数据处理问题。通过类比图书馆管理系统,详细解释了Hadoop的两大组件:HDFS(分布式文件系统)和MapReduce(分布式计算模型)。具体实现了单词统计任务,并扩展支持CSV和JSON格式的数据解析。为了提升性能,引入了Combiner减少中间数据传输,以及自定义Partitioner解决数据倾斜问题。最后总结了Hadoop在大数据处理中的重要性,鼓励Java开发者学习Hadoop以拓展技术边界。
50 7
|
1月前
|
java异步判断线程池所有任务是否执行完
通过上述步骤,您可以在Java中实现异步判断线程池所有任务是否执行完毕。这种方法使用了 `CompletionService`来监控任务的完成情况,并通过一个独立线程异步检查所有任务的执行状态。这种设计不仅简洁高效,还能确保在大量任务处理时程序的稳定性和可维护性。希望本文能为您的开发工作提供实用的指导和帮助。
110 17
招行面试: 分布式调度 设计,要考虑 哪些问题?
45岁资深架构师尼恩在读者交流群中分享了关于设计分布式调度框架时需考虑的关键问题。近期有小伙伴在面试招商银行时遇到了相关难题,因准备不足而失利。为此,尼恩系统化地梳理了以下几点核心内容,帮助大家在面试中脱颖而出,实现“offer直提”。
Java线程池提交任务流程底层源码与源码解析
【11月更文挑战第30天】嘿,各位技术爱好者们,今天咱们来聊聊Java线程池提交任务的底层源码与源码解析。作为一个资深的Java开发者,我相信你一定对线程池并不陌生。线程池作为并发编程中的一大利器,其重要性不言而喻。今天,我将以对话的方式,带你一步步深入线程池的奥秘,从概述到功能点,再到背景和业务点,最后到底层原理和示例,让你对线程池有一个全新的认识。
77 12