在java中的某些条件下阻塞线程

时间:2011-11-16 18:54:13

标签: java java.util.concurrent

也许这是一个非常愚蠢的问题,但请听我说。我有一个用例,我得到许多并发请求,为特定的输入日期做某事。如果在同一输入日期收到两个并发请求,则后续请求不应继续,直到先前请求完全完成(有充分理由)。使用标准java.util.concurrent组件来实现此目的的最佳方法是什么?我最初的想法是围绕一个LockFactory来销售锁并保留一份副本以表明它正在使用中并且随后的请求将等待()。然而,这似乎有很多锅炉板代码 - 任何更简单的技巧,是在逃避我?

提前致谢!

5 个答案:

答案 0 :(得分:1)

听起来像你必须排队请求并一次处理一个。也许是java.util.concurrent中的BlockingQueue?

答案 1 :(得分:1)

您需要创建一个ThreadPoolExecutor来在多个线程中执行请求。您还需要有一个输入日期列表,现在处理。此列表应具有同步访问器和putIfAbsent方法。在将任务发送到队列之前检查它的输入日期是否现在未处理。如果现在处理它,将此任务移动到队列的末尾并尝试运行下一个任务。任务完成后,从列表中删除其输入日期。

答案 2 :(得分:1)

我假设您已经拥有一个系统,其中线程可以接收输入请求并处理它们,而不会丢失或复制任何请求,从而解决任何锁定问题。然后,您需要的是每个线程在某处记录当前正在处理的事物的输入日期。当线程检查输入请求时,它首先检查日期,查看当前是否正在处理具有该日期的任何请求,如果它们是,那么它将该请求留在队列中并接受下一个请求。

您需要进行一定程度的锁定,以确保在测试时不会更新“当前正在进行的工作”。

答案 3 :(得分:1)

您可以在日期的时间哈希个别锁。

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(); 

等等

答案 4 :(得分:0)

您正在寻找的简单技巧是线程池“with in order processing”模式。 Here is a thread which explain the pattern and various solutions to implement it