也许这是一个非常愚蠢的问题,但请听我说完。我有一个用例,我收到许多并发请求来为特定的输入日期做某事。如果在同一输入日期收到两个并发请求,则后续请求不应继续,直到前一个请求完全完成(有充分理由)。使用标准 java.util.concurrent 组件来实现这一目标的最佳方法是什么?我最初的想法是拥有一个 LockFactory,它将出售锁并保留一份副本以表明它正在使用中,并且后续请求将在其上等待()。然而,这似乎有很多样板代码 - 有什么更简单的技巧让我难以捉摸吗?
提前致谢!
也许这是一个非常愚蠢的问题,但请听我说完。我有一个用例,我收到许多并发请求来为特定的输入日期做某事。如果在同一输入日期收到两个并发请求,则后续请求不应继续,直到前一个请求完全完成(有充分理由)。使用标准 java.util.concurrent 组件来实现这一目标的最佳方法是什么?我最初的想法是拥有一个 LockFactory,它将出售锁并保留一份副本以表明它正在使用中,并且后续请求将在其上等待()。然而,这似乎有很多样板代码 - 有什么更简单的技巧让我难以捉摸吗?
提前致谢!
我假设您已经有一个系统,其中线程可以接受输入请求并处理它们,而不会丢失或复制任何内容,并处理任何锁定问题。然后,您所需要的只是让每个线程在某处记录它当前正在处理的事情的输入日期。当一个线程检查输入请求时,它首先检查日期,查看当前是否正在处理具有该日期的任何请求,如果是,则将该请求留在队列中并接受下一个请求。
您将需要一定量的锁定以确保“当前正在处理的条目”在您测试时不在更新过程中。
您需要创建一个 ThreadPoolExecutor 来在多个线程中执行请求。您还需要有一个输入日期列表,现在正在处理。此列表应具有同步访问器和 putIfAbsent 方法。在将任务发送到队列之前,请检查它的输入日期是否现在未处理。如果现在正在处理,则将此任务移动到队列的末尾并尝试运行下一个任务。任务完成后,从列表中删除其输入日期。
您可以在日期时间上散列单个锁。
private static final ConcurrentMap<Long,Lock> dateLock = new ConcurrentHashMap<Long,Lock>();
public static Lock getLock(Date date){
Lock lock = dateLock.get(date.getTime());
if(lock == null){
Lock lock = new ReentrantLock();
Lock temp =dateLock.putIfAbsent(lock);
lock = temp == null ? lock : temp;
}
return lock;
}
如果您需要同一天而不一定是毫秒的确切日期,您可以执行类似的操作
private static final ConcurrentMap<String,Lock> dateLock = new ConcurrentHashMap<String,Lock>();
public static Lock getLock(Date date){
String formattedDate = new SimpleDateFormat("MM\dd\yyyy").parse(date);
Lock lock = dateLock.get(formattedDate);
if(lock == null){
Lock lock = new ReentrantLock();
Lock temp =dateLock.putIfAbsent(lock);
lock = temp == null ? lock : temp;
}
return lock;
}
然后任何需要在约会时互斥的请求
Date date = ...;
Lock lock = getLock(date);
lock.lock();
等等
在我看来,您必须将您的请求排队并一次处理一个。那么也许是来自 java.util.concurrent 的 BlockingQueue?
您正在寻找的简单技巧是“按顺序处理”模式的线程池。 这是一个解释模式和实现它的各种解决方案的线程