我有一个包含约5000个对象的数组。对于每个对象,我计划执行一些逻辑。每个对象的逻辑相同。我想尽我所能,所以我来到了ExecutorService,它位于java.util.cuncurrent中。我决定在一个线程中处理100个对象,因此我将总数(〜5k)分为间隔
private List<Integer> divideIntoIntervals(Integer total)
{
List<Integer> intervals = new ArrayList<Integer>();
intervals.add(0);
int n = total / PART_SIZE;
int leftover = total % PART_SIZE;
if(n!=0)
{
intervals.add(PART_SIZE);
for (int i=2; i<=n; i++)
{
intervals.add(PART_SIZE*i);
}
intervals.add(PART_SIZE*n+leftover);
}
return intervals;
}
因此,该数组将是:0、100、200、300,...,5000、5041。您会建议使用哪种当前列表?我正计划创建逻辑,该逻辑在另一个间隔内寻找我的cuncurrent数组。
您可能不需要并发列表。只要您在线程执行工作时不修改列表,就可以创建一个单独的列表Runnable
来在其自己的范围内工作,并将那些可运行对象提交给ThreadPoolExecutorService
具有适当数量线程(在您的情况下为〜50)的线程。任务将自动在线程之间平均分配:
ExecutorService executor = Executors.newFixedThreadPool(list.size() / 100 + 1);
// (+1 in case there are less than 100 items)
for (int i = 0; i < list.size(); i += 100) {
final int start = i;
executor.execute(() -> {
int end = start + 100;
if (end > list.size()) {
end = list.size();
}
for (int j = start; j < end; ++j) {
list.get(j).doYourLogicHere();
}
});
}
如果您不确定要不要在这些任务之外修改列表,则应根据要处理的修改内容更改代码。例如,如果可以在处理过程中将新项目添加到列表中,并且您不在乎此阶段是否处理了这些新项目,那么您可能希望使用aCopyOnWriteArrayList
并更改上面的内部循环以使用迭代器,而不是基于int的索引。这将导致代码使用创建迭代器时所用列表的快照(并且如果您在进行迭代时未进行任何修改,则不会进行任何实际复制)。根据追加新项目的时间,此快照可能包括也可能不包括这些快照,但是至少它是一致的,并且没有中断。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句