如何尽快获取锁列表中的锁?
How to acquire a lock among a list of locks as soon as possible?
我有这个极其简化的 class,运行锁定任务。锁是为了防止同一任务同时 运行 两次。
任务本身可以根据需要 运行 多次。
class Job {
private Lock lock;
// Constructor, getters, setters, etc. removed to stay short
public boolean execute (int maxWaitTime) {
if (lock.tryLock(maxWaitTime, TimeUnit.MILISECONDS)) {
try {
// do some lengthy job under the lock
} finally {
lock.unlock();
}
return true;
}
else return false;
}
}
现在,假设我有这些工作的列表:
List<Job> jobs = ... ;
列表中的所有工作性质相同。我只想执行列表中的一个,暂时忽略所有其他的。
我只想执行第一个可用的任务,在当前持有锁之后等待尽可能少的任务(对应于当前 运行ning 的任务)。
过了一会儿,比方说 10 秒,如果所有作业仍然很忙,那么我放弃并且不执行任何作业(当然,实际上,在这种情况下会发生一些不同的事情)。
首先,我想到了这个:
for (Job job: jobs) {
if (job.execute(10000)) return; // one job has been executed
}
然后意识到,如果我有 N 个工作,那么我可能会在放弃之前等待总共 10*N
秒而不是仅 10 秒,以防没有空闲工作并且 none 在此期间可用。
然后,我想到了这个:
long start = System.currentTimeMillis();
while (true) {
for (Job job: jobs) {
if (System.currentTimeMillis() -start > 10000) return; // give up after 10 seconds
if (job.execute(0)) return; // one job has been executed
}
我不是在等待 运行ning 任务,只是在 10 秒内执行第一个可用的任务,我会尽快执行,这很好。
但是,我在这里做 active wait,众所周知,这对一般性能来说很糟糕,应该避免。
我的第三次尝试是:
for (Job job: jobs) {
if (job.execute(10000/jobs.size())) return; // one job has been executed
}
现在我最多等10秒。但这不是最佳解决方案。
假设我有 10 个工作,第 9 个是免费的,而前 8 个留在 运行ning。那样的话,我还是白白等了8秒,才找到空闲的执行。
我们可以做得更好吗?
作为一个偏好,我想要一个没有外部依赖的标准 Java 11 解决方案。我的示例的 Job class 在我的控制之下,因此如果需要我可以重构它。
感谢您的回答。
您需要尝试从 N
个不同的线程获取锁 10 秒。如果你成功地举起一个标志(你需要做到线程安全),如果标志已经举起释放当前锁,否则继续执行任务。
PS:N
是职位数。
我有这个极其简化的 class,运行锁定任务。锁是为了防止同一任务同时 运行 两次。 任务本身可以根据需要 运行 多次。
class Job {
private Lock lock;
// Constructor, getters, setters, etc. removed to stay short
public boolean execute (int maxWaitTime) {
if (lock.tryLock(maxWaitTime, TimeUnit.MILISECONDS)) {
try {
// do some lengthy job under the lock
} finally {
lock.unlock();
}
return true;
}
else return false;
}
}
现在,假设我有这些工作的列表:
List<Job> jobs = ... ;
列表中的所有工作性质相同。我只想执行列表中的一个,暂时忽略所有其他的。 我只想执行第一个可用的任务,在当前持有锁之后等待尽可能少的任务(对应于当前 运行ning 的任务)。
过了一会儿,比方说 10 秒,如果所有作业仍然很忙,那么我放弃并且不执行任何作业(当然,实际上,在这种情况下会发生一些不同的事情)。
首先,我想到了这个:
for (Job job: jobs) {
if (job.execute(10000)) return; // one job has been executed
}
然后意识到,如果我有 N 个工作,那么我可能会在放弃之前等待总共 10*N
秒而不是仅 10 秒,以防没有空闲工作并且 none 在此期间可用。
然后,我想到了这个:
long start = System.currentTimeMillis();
while (true) {
for (Job job: jobs) {
if (System.currentTimeMillis() -start > 10000) return; // give up after 10 seconds
if (job.execute(0)) return; // one job has been executed
}
我不是在等待 运行ning 任务,只是在 10 秒内执行第一个可用的任务,我会尽快执行,这很好。 但是,我在这里做 active wait,众所周知,这对一般性能来说很糟糕,应该避免。
我的第三次尝试是:
for (Job job: jobs) {
if (job.execute(10000/jobs.size())) return; // one job has been executed
}
现在我最多等10秒。但这不是最佳解决方案。 假设我有 10 个工作,第 9 个是免费的,而前 8 个留在 运行ning。那样的话,我还是白白等了8秒,才找到空闲的执行。
我们可以做得更好吗?
作为一个偏好,我想要一个没有外部依赖的标准 Java 11 解决方案。我的示例的 Job class 在我的控制之下,因此如果需要我可以重构它。
感谢您的回答。
您需要尝试从 N
个不同的线程获取锁 10 秒。如果你成功地举起一个标志(你需要做到线程安全),如果标志已经举起释放当前锁,否则继续执行任务。
PS:N
是职位数。