繁体   English   中英

如何使用ExecuterService划分线程?

[英]How can I divide into threads using ExecuterService?

我有一个包含约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 。 。 任务将自动在线程之间平均分配:

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

如果您不确定是否要在这些任务之外修改列表,则应根据要处理的修改内容更改代码。 例如,如果可以在处理过程中将新项目添加到列表中,并且您不在乎在此阶段是否处理这些新项目,那么您可能希望使用CopyOnWriteArrayList并将上面的内部循环更改为使用迭代器而不是基于int的索引。 这将导致代码使用创建迭代器时所用列表的快照(并且如果您在进行迭代时未进行任何修改,则不会进行任何实际复制)。 根据追加新项目的时间,此快照可能包括也可能不包括这些快照,但是至少它是一致的,没有中断。

您也可以使用newCachedThreadPool方法。 这将创建一个线程池,该线程池会根据需要创建新线程,但是将在先前构造的线程可用时重用它们。 资源

我如何使用它的示例:

        //  Create an executor service with  a thread pool that creates new threads as needed,
        //  but will reuse previously constructed threads when they are available
        ExecutorService executorService = Executors.newCachedThreadPool();

        Integer finalMinValue = minValue;
        Integer finalMaxValue = maxValue;

        executorService.execute(() -> {
            // Initialise buckets
            int bucketCount = (finalMaxValue - finalMinValue) / bucketSize + 1;
            List<List<Integer>> buckets = new ArrayList<>(bucketCount);

            for (int i = 0; i < bucketCount; i++) {
                buckets.add(new ArrayList<>());
            }


            // Distribute input array values into buckets
            for (Integer anArrayElement : arrayToSort) {
                buckets.get((anArrayElement - finalMinValue) / bucketSize).add(anArrayElement);

            }

            //  Sort buckets and place back into input array
            //  Loop through the contents of each bucket
            for (List<Integer> bucket : buckets) {


                Integer[] bucketArray = new Integer[bucket.size()];

                bucketArray = bucket.toArray(bucketArray);

                InsertionSort.sort(bucketArray);

                for (Integer aBucketArray : bucketArray) {
                    arrayToSort[currentIndex] = aBucketArray;
                    incrementSync();
                }
            }
        });

Github上可以找到有关此实现的更多信息

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM