java - 这个用例的最佳集合是什么?
java - what is the best collection for this use case?
我有一个密集更新列表,所以我将它们组合在一起并在单个线程中作为批处理作业执行。其他线程可以随时发送他们的更新。
class ItemUpdateJob {
int itemId;
int number;
}
在安排作业排队等待更新时,我想要一个集合,如果它已经存在,我可以在其中修改作业(假设 itemId 为键)。在这个例子中:
existingItemJobInQueue.number += requestedItemJob.number;
所以队列不会开始有数千个相同项目的作业。当作业开始执行时,我需要以某种方式遍历队列,但是在更新作业时,不应更新它(每个项目都应该有自己的锁吗?)。
for (ItemUpdateJob job : jobQueue) {
updateItem(job);
}
作业更新后,应立即将其从队列中删除。做这个的最好方式是什么?目前我正在考虑使用以项目 ID 作为键的 HashMap,然后每个项目都有一个锁,防止在更新项目时修改现有作业。虽然,这会导致等待更新完成(锁被释放)时停止。
在我看来,您似乎需要多个集合的组合。也许是这样的?
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
实施具有容量限制,显然这需要同步。
我有一个密集更新列表,所以我将它们组合在一起并在单个线程中作为批处理作业执行。其他线程可以随时发送他们的更新。
class ItemUpdateJob {
int itemId;
int number;
}
在安排作业排队等待更新时,我想要一个集合,如果它已经存在,我可以在其中修改作业(假设 itemId 为键)。在这个例子中:
existingItemJobInQueue.number += requestedItemJob.number;
所以队列不会开始有数千个相同项目的作业。当作业开始执行时,我需要以某种方式遍历队列,但是在更新作业时,不应更新它(每个项目都应该有自己的锁吗?)。
for (ItemUpdateJob job : jobQueue) {
updateItem(job);
}
作业更新后,应立即将其从队列中删除。做这个的最好方式是什么?目前我正在考虑使用以项目 ID 作为键的 HashMap,然后每个项目都有一个锁,防止在更新项目时修改现有作业。虽然,这会导致等待更新完成(锁被释放)时停止。
在我看来,您似乎需要多个集合的组合。也许是这样的?
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
实施具有容量限制,显然这需要同步。