2

伙计们。我有一个任务我无法解决,因为我对多线程很陌生。我想编写一个将维护以下语义的类:

interface TokenAwareTaskExecutor(){
   //Callable<Long> returns the time the task finishes.
   public void submitTask(String token, Callable<Long> task);
   public long getDelay();
}

在提交任务时,服务会查找之前的调用是否添加了这样的令牌。如果是这样,则该任务应在延迟之后以及任何其他具有相同令牌的已提交任务已执行之后提交。如果不存在这样的令牌,请添加它并立即提交任务。总而言之,我想实现一个负载平衡策略,允许独立处理具有给定频率的唯一令牌。你能指导我看什么吗?

4

2 回答 2

0

如果没有太多不同的标记,一种解决方案可能是将每个标记映射到ScheduledThreadPoolExecutor. 然后,如果在地图中找到了执行者,则延迟调度任务。否则,立即创建一个新的执行和计划。

另一种方法是只有一个ScheduledThreadPoolExecutor和一个将令牌映射到一个ScheduleInfo对象的映射,该对象由一个原子计数器组成,该计数器计算该令牌正在等待的任务数量以及具有该令牌的最后一个任务的调度时间。对计数器和时间的任何更改都必须同时发生并同步。

我们将每个传入任务包装在一个外部 Callable 中,该 Callable 在调度时使用in 中的synchronized方法递增计数器。如果计数器为零,我们将立即调度并将调度时间设置为当前时间。如果计数器大于零,我们将延迟添加到 scheulding 时间并安排该确切时间。enter()ScheduleInfo

synchronized当内部任务完成后,外部任务必须再次递减计数器,这发生exit()ScheduleInfo. 我不确定如何解释延迟(调用之间的时间一个任务结束与下一个任务开始之间的时间)。在后一种情况下,我们也必须在这里调整调度时间。同样,重要的是enter不能exit重叠,因此必须同步。

没有尝试任何代码,这就是我的想法,所以我欢迎任何批评。

于 2013-04-06T15:05:28.537 回答
0

实施将涉及以下内容:

  1. 需要存储已提交的令牌以及这些令牌请求的状态:为了实现这一点,我将创建一个内部类,其中包含令牌名称、最后请求的状态、提交时间和最后请求的结束时间。我将使用 ConcurrentHashmap 将相应的字符串标记存储为键,并将每个 bean 的实例存储为值,并且每当有请求进入时,我将通过使用同步块来锁定该 bean。

  2. 每次请求到来时,它都会检查 map 中是否存在令牌条目,如果不存在,它将创建一个条目并继续执行任务。如果存在条目,它将尝试获取 bean 实例的锁定,这意味着如果已在 bean 上获取锁定,那么它将等待。

  3. 一旦一个请求完成了它的工作,它会在释放锁之前更新它在相应 bean 中的状态。

以上2点基本上为实现设置了一个freamork,您可以扩展它以实现其他方面,例如如果出现超过2个以上的多个请求然后依次排队[您可以使用fairnes lock],如果您想添加任何多个请求之间的额外延迟,那么这也可以完成

于 2013-04-06T17:29:51.067 回答