Java信号量-未经事先发布而授予的许可
我写这个问题是因为我们在一个qa环境中遇到了一个场景,在这个场景中,信号量似乎失败了。 我们只有一个信号灯:Java信号量-未经事先发布而授予的许可,java,concurrency,quartz-scheduler,semaphore,deltaspike,Java,Concurrency,Quartz Scheduler,Semaphore,Deltaspike,我写这个问题是因为我们在一个qa环境中遇到了一个场景,在这个场景中,信号量似乎失败了。 我们只有一个信号灯: 专用信号量锁=新信号量(1); 一个线程(石英作业)正在运行,持有所获取的锁,然后触发另一个任务,并在执行过程中执行。 两个作业都获取并释放锁,因此如果第一个作业被延迟,后者必须等待第一个作业释放锁 奇怪的是后者没有等待,它只是通过了锁。acquire() 场景一点也不复杂,代码从一开始就可以工作。到目前为止我们还没能重现它,我不知道。可能是故障 我想知道是否有人知道Quartz和Ja
专用信号量锁=新信号量(1);
一个线程(石英作业)正在运行,持有所获取的锁,然后触发另一个任务,并在执行过程中执行。 两个作业都获取并释放锁,因此如果第一个作业被延迟,后者必须等待第一个作业释放锁
奇怪的是后者没有等待,它只是通过了锁。acquire() 场景一点也不复杂,代码从一开始就可以工作。到目前为止我们还没能重现它,我不知道。可能是故障 我想知道是否有人知道Quartz和Java信号量之间是否存在某种已知的不兼容,或者Java信号量在某些情况下是否会失败 编辑 还有一个细节,它是一个基于Deltaspike CDI框架构建的应用程序 这是处理锁的单例:import java.util.concurrent.Semaphore;
public class Lock {
private Lock() {}
private static class SingletonHolder {
public static final Lock INSTANCE = new Lock();
}
/**
* Use this method to get a reference to the singleton instance of
* {@link Lock}
*
* @return the singleton instance
*/
public static Lock getInstance() {
return SingletonHolder.INSTANCE;
}
/**
* we allow only one thread at at time
*/
private Semaphore lock = new Semaphore(1);
public void getLock() throws InterruptedException {
lock.acquire();
}
public void releaseLock() {
lock.release();
}
}
这是第一份工作:
@Scheduled(cronExpression = "{cronExp1}")
public class Job1 implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
method1();
}
public void method1(){
long threadId = Thread.currentThread().getId();
try{
logger.debug("Thread # " + threadId + "Requesting lock...");
Lock.getInstance().getLock();
logger.debug("Thread # " + threadId + "Lock acquired.");
//...some logic
}catch (PersistenceException e) {
//.. handling exception
}catch (Exception e) {
//.. handling exception
}finally {
Lock.getInstance().releaseLock();
logger.debug("Thread # " + threadId + "Lock released.");
}
}
}
这是第二项工作:
@Scheduled(cronExpression = "{cronExp2}")
public class Job2 implements Job {
@Override
public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException {
long threadId = Thread.currentThread().getId();
try{
logger.debug("Thread # " + threadId + "Requesting lock...");
Lock.getInstance().getLock();
logger.debug("Thread # " + threadId + "Lock acquired.");
//...some logic
}catch (PersistenceException e) {
//.. handling exception
}catch (Exception e) {
//.. handling exception
}finally {
Lock.getInstance().releaseLock();
logger.debug("Thread # " + threadId + "Lock released.");
}
}
}
如您所见,作业(逻辑除外)之间的唯一区别在于,作业1进入方法1内的关键区域,而作业2进入执行方法内的关键区域。您能否分享一个最小且可验证的示例,说明所述的
锁如何在您的代码中使用?谢谢@MickMnemonic,我刚刚用代码信息更新了这个问题,您如何知道两个线程能够同时获得许可?我注意到您的finally
块在释放许可证之前不会打印消息。因此,从理论上讲,第二个线程在第一个线程发布许可证之后,但在第一个线程打印其消息之前,打印“Lock acquired”消息是可能的。捕捉得好,但我从每个作业的逻辑部分的日志中知道。我有很多来自Job2的日志条目和来自Job1的日志条目,这是以前从未发生过的事情。时间间隔为30分钟,第一份工作耗时45分钟。在第31分钟,或多或少,我开始看到两个作业的混合日志。除此之外,由于它们都与数据库交互,我看到了其中的不一致性,这是由于重叠造成的。希望它能帮助这些作业在同一个JVM中运行吗?