【问题标题】:java - what is the best collection for this use case?java - 这个用例的最佳集合是什么?
【发布时间】:2022-01-23 15:24:33
【问题描述】:

我有一个密集更新列表,因此我将它们组合在一起,并在单个线程中将它们作为批处理作业执行。其他线程可以随时发送他们的更新。

class ItemUpdateJob {
    int itemId;
    int number;
}

在安排要排队等待更新的作业时,我想要一个集合,如果作业已经存在,我可以在其中修改它(假设 itemId 作为键)。在这个例子中:

existingItemJobInQueue.number += requestedItemJob.number;

因此队列不会开始为同一项目提供数千个作业。当作业开始执行时,我需要以某种方式遍历队列,但是在更新作业时,不应该更新它(每个项目都应该有自己的锁吗?)。

for (ItemUpdateJob job : jobQueue) {
    updateItem(job);
}

更新作业后,应立即将其从队列中删除。做这个的最好方式是什么?目前我正在考虑使用以项目 id 作为键的 HashMap,然后每个项目都有一个锁,以防止在更新项目时修改现有作业。虽然,这会导致它在等待更新完成(释放锁)时停止。

【问题讨论】:

  • 在更新之前从队列中删除元素怎么样?这会产生问题吗?
  • @DarioPetrillo 这会起作用,因为任何新的更新都会被添加到下一批中。
  • 那我可能会朝那个方向走,因为你不再需要很多锁了
  • 那么number字段是统计提交到队列的次数?也许重命名为特定的名称,例如 countSubmissions,以在此处澄清您的问题陈述。
  • @BasilBourque 对不起,名字不好,只是要处理的数据,与队列无关。

标签: java collections


【解决方案1】:

在我看来,您似乎需要多个系列的组合。也许是这样的?

public class JobHandler {

  //jobs still in the queue, map for a quick lookup
  private final Map<Integer, ItemUpdateJob> waitingJobs;
  //jobs still waiting to be run
  private final Queue<ItemUpdateJob> jobQueue;

  public JobHandler(Collection<ItemUpdateJob> jobs) {
    this.waitingJobs = new HashMap<>();
    this.jobQueue = new LinkedList<>();
    this.init(jobs);
  }
  
  private void init(Collection<ItemUpdateJob> jobs) {
    for (ItemUpdateJob job : jobs) {
      this.waitingJobs.put(job.itemId, job);
      this.jobQueue.add(job);
    }
  }

  public ItemUpdateJob getNextJobToRun() {
    ItemUpdateJob nextJob = this.jobQueue.poll();
    if (nextJob != null) {
      this.waitingJobs.remove(nextJob.itemId);
    }
    return nextJob;
  }

  public void addJob(ItemUpdateJob job) {
    this.waitingJobs.put(job.itemId, job);
    this.jobQueue.add(job);
  }

  public boolean updateJob(ItemUpdateJob updateJob) {
    if (this.waitingJobs.containsKey(updateJob.itemId)) {
      //job is currently waiting for execution, so update it
      this.waitingJobs.get(updateJob.itemId).number += updateJob.number;
      return true;
    } else {
      //job is currently being run, or no such job at all
      //so adding it at the end of the queue to wait for it's turn
      this.addJob(updateJob);
      return false;
    }
  }
}

java.util.Queue 看起来很匹配 - 作业的 FIFO 执行顺序和 Map 用于在更新当前等待作业时快速查找。请记住,一些Queue 实现有容量限制,显然这需要同步。

【讨论】:

    猜你喜欢
    • 2017-04-05
    • 1970-01-01
    • 1970-01-01
    • 2011-02-21
    • 1970-01-01
    • 1970-01-01
    • 2010-10-03
    • 2018-07-16
    • 2020-04-19
    相关资源
    最近更新 更多