首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >是否存在带有超时的Java实现

是否存在带有超时的Java实现
EN

Stack Overflow用户
提问于 2015-07-23 12:29:40
回答 4查看 3K关注 0票数 0

我有一个spring应用程序,它可以在集群环境中运行。在该环境中,我使用Redis (和Redisson)作为分布式锁服务。

许多锁用于保护某些任务,这些任务一次只能运行一次,或者只能每X秒启动一次。

应用程序还能够在独立模式下运行(没有redis)。

但是,对于这种情况,我需要一个不同的锁服务实现。我认为这非常简单,因为我只需要在本地创建一个带有特定超时的Lock实例(例如,对于“只运行2分钟”)。然而,当我环顾四周时,我找不到Java接口的任何实现,它支持为锁设置一个超时(这样它就可以在那之后自动解锁)。

有这样的东西吗,或者有一种非常简单的方法(就代码行而言)我可以自己实现它,而我只是错过了这个方法?

锁推动应该如何表现:

  • 当它处于活动状态时,其他线程无法锁定它(与任何其他锁一样)
  • 理想情况下,拥有的线程应该能够再次调用lock(long timoutMs)来扩展锁(将超时设置为给定的时间)。

编辑:一个具体的例子似乎可以帮助我理解我想要的是什么:

  • 假设服务器有一个HTTP操作"doExpesiveTask“
  • 每当调用此任务时,我的应用程序就会转到它的ockService“并调用.tryAcquireLock("expensiveTaskId", 10, TimeUnit.Minutes),如果它得到了锁,就会返回一个布尔值。
  • 如果它获得了锁,它就启动任务。
  • 如果它没有得到锁,它不会,并向用户表明“你必须更耐心”

在分布式设置中,lockService的实现使用redis (和Redisson库)分布式锁(这已经很好了)!为了在分布式模式和独立模式之间进行非常简单的切换,我只想要一个不依赖任何外部服务的lockService实现。因此,我只需要一个Lock的实现,它支持超时。这样,我就可以在锁服务中拥有一个ConcurrentHashMap,它将锁ids映射到这些锁实例。

为什么不简单地使用映射将锁ids映射到时间对象:因为我还需要防止其他线程重新锁定(延长由另一个线程获得的锁的生存期)。

EN

回答 4

Stack Overflow用户

发布于 2015-07-23 13:04:57

您的描述有点模棱两可,因为您说的是锁,但实际上您并没有锁定资源(或者没有提供示例)。我觉得你的问题和日程安排有关。

因为您已经使用了Spring,所以可以查看它的调度选项。最近的版本允许您使用@Scheduled注释来触发该注释。@EnableScheduling启动后台任务执行器。您可以将它与Spring配置文件组合起来,以确保只有在传递概要文件(例如作为JVM参数)时,这些配置文件才会生效。

从文档中复制:

代码语言:javascript
运行
复制
package hello;

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

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

@Component
public class ScheduledTasks {

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

    @Scheduled(fixedRate = 5000)
    public void reportCurrentTime() {
        System.out.println("The time is now " + dateFormat.format(new Date()));
    }
}

并使:

代码语言:javascript
运行
复制
package hello;

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

@SpringBootApplication
@EnableScheduling
public class Application {

    public static void main(String[] args) throws Exception {
        SpringApplication.run(Application.class);
    }
}

这里有一个快速指南:

弹簧文档

服务代码(您可能希望与枚举器一起使用字符串以提高清晰度):

代码语言:javascript
运行
复制
import org.apache.commons.collections4.map.PassiveExpiringMap;

public class StandAloneLockService {
    private Map ordinaryLocks;
    private Map expiringLocks;

    public StandAloneLockService() {
        this.ordinaryLocks = new HashMap<String, Long>();
        this.expiringLocks = new PassiveExpiringMap<String, Long>(2L,
                TimeUnit.MINUTES);
    }

    public synchronized boolean accquireLock(String task) {
        if (ordinaryLocks.containsKey("task")
                || expiringLocks.containsKey("task")) {
            return false;
        } else {
            return handle("task");
        }
    }

    private boolean handle(String jdk7) {
        switch (jdk7) { // logic 
        }
    }
    private void releaseLock(String task) {
        switch (task) { // logic 
        }
    }
}
票数 2
EN

Stack Overflow用户

发布于 2017-08-08 23:46:28

您可以尝试在ReentrantLock的等待呼叫中放置超时,例如:

代码语言:javascript
运行
复制
public class MessageUtil {
  private static final Lock lock = new ReentrantLock();

  public enum Conditions {
     BAR_INIT(lock.newCondition()),
     TEST_DELAY(lock.newCondition());

     Condition condition;

     private Conditions(Condition condition) {
         this.condition = condition;
     }
  }

  public static void await(Conditions condition, int timeout) throws Interrupted Exception {
     lock.lock();
     condition.condition.await(timeout, TimeUnit.SECONDS);
     lock.unlock();
  }

  public static void signalAll(Conditions condtition) {
     lock.lock();
     condition.condition.signalAll();
     lock.unlock();
  }
}

这个实用工具类允许您使用等待方法等待某个条件,比如等待Bar类在测试中完成初始化或等待某个步骤,然后使用signalAll方法结束等待条件并恢复正常操作。

票数 2
EN

Stack Overflow用户

发布于 2015-07-23 12:38:04

对象类中有一个方法:public final void wait(long timeout)。请参阅http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#wait(long)

您只能在同步块中调用它。

作为示例(来自javadoc):

代码语言:javascript
运行
复制
synchronized (obj) {
         while (<condition does not hold>)
             obj.wait(timeout);
         ... // Perform action appropriate to condition
     }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31587391

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档