了解工作窃取算法

时间:2019-06-26 15:54:05

标签: java-threads work-stealing

关于这个算法,我读了很多东西。在解释此算法时,单词: work stealing algorithm [closed]

  

那些分叉的子任务可以递归   自己创建更多子任务,从而填补了   并行工作线程。如果一个线程完成但什么都没有   要做的更多,他可以从另一个线程的队列中“窃取”工作。

我了解到此算法是新算法,在Executors.newCachedThreadPool / Executors.newFixedThreadPool中不存在
我希望看到一个线程只能处理其队列中的工作。 我创建了一个小程序来递归创建线程。见下文。 我怎么能看到它没有使用窃取算法的工作?

public static void main(String[] args) throws Exception {
    int[] myArray = IntStream.rangeClosed(1, 10).toArray();

        ExecutorService executorService = Executors.newFixedThreadPool(5);
        CustomCallable customCallable = new CustomCallable(myArray, executorService);
        customCallable.call();
        executorService.shutdownNow();
}
public class CustomCallable implements Callable<Integer> {
    private static final int THRESHOLD = 2;
    private int[] array;
    private ExecutorService executorService;

    public CustomCallable(int[] array, ExecutorService executorService) {
        this.array = array;
        this.executorService = executorService;
    }

    @Override
    public Integer call() throws Exception {
        int sum = 0;
        log.debug(" start [{}] ", Arrays.toString(array) );
        if (array.length > THRESHOLD) {
            List<Callable<Integer>> dividedTasks = createSubtasks(array, executorService);
            sum = executorService.invokeAll(dividedTasks).stream()
                    .mapToInt(feature -> {
                        try {
                            return feature.get();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        } catch (ExecutionException e) {
                            e.printStackTrace();
                        }
                        return 0;
                    })
                    .sum();
       } else {
            sum = processing(array);
        }
        log.debug(" sum[{}]={} ", Arrays.toString(array) ,sum);
        return sum;
    }

    private List<Callable<Integer>> createSubtasks(int[] array, ExecutorService executorService) {
        int[] arr1 = Arrays.copyOfRange(array, 0, array.length / 2);
        int[] arr2 = Arrays.copyOfRange(array, array.length / 2, array.length);
        List<Callable<Integer>> dividedTasks = new ArrayList<>();
        dividedTasks.add(new CustomCallable(arr1, executorService));
        dividedTasks.add(new CustomCallable(arr2, executorService));
        return dividedTasks;
    }

    private Integer processing(int[] array) {
        int result = Arrays.stream(array)
                .sum();
        return result;
    }
}

这是输出:

[main] DEBUG com.example.CustomCallable -  start [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]  
[pool-2-thread-1] DEBUG com.example.CustomCallable -  start [[1, 2, 3, 4, 5]]  
**[pool-2-thread-3] DEBUG com.example.CustomCallable -  start [[1, 2]]**  
[pool-2-thread-2] DEBUG com.example.CustomCallable -  start [[6, 7, 8, 9, 10]]  
[pool-2-thread-4] DEBUG com.example.CustomCallable -  start [[3, 4, 5]]  
[pool-2-thread-5] DEBUG com.example.CustomCallable -  start [[6, 7]]  
**[pool-2-thread-3] DEBUG com.example.CustomCallable -  sum[[1, 2]]=3**  
[pool-2-thread-5] DEBUG com.example.CustomCallable -  sum[[6, 7]]=13  
**[pool-2-thread-3] DEBUG com.example.CustomCallable -  start [[8, 9, 10]]**  
[pool-2-thread-5] DEBUG com.example.CustomCallable -  start [[3]]  
[pool-2-thread-5] DEBUG com.example.CustomCallable -  sum[[3]]=3  
[pool-2-thread-5] DEBUG com.example.CustomCallable -  start [[4, 5]]  
[pool-2-thread-5] DEBUG com.example.CustomCallable -  sum[[4, 5]]=9  
[pool-2-thread-5] DEBUG com.example.CustomCallable -  start [[8]]  
[pool-2-thread-5] DEBUG com.example.CustomCallable -  sum[[8]]=8  
[pool-2-thread-5] DEBUG com.example.CustomCallable -  start [[9, 10]]  
[pool-2-thread-5] DEBUG com.example.CustomCallable -  sum[[9, 10]]=19  
**[pool-2-thread-3] DEBUG com.example.CustomCallable -  sum[[8, 9, 10]]=27**  
[pool-2-thread-4] DEBUG com.example.CustomCallable -  sum[[3, 4, 5]]=12  
[pool-2-thread-2] DEBUG com.example.CustomCallable -  sum[[6, 7, 8, 9, 10]]=40  
[pool-2-thread-1] DEBUG com.example.CustomCallable -  sum[[1, 2, 3, 4, 5]]=15  
[main] DEBUG com.example.CustomCallable -  sum[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]=55 


您可以看到:
主触发线程2和线程1
线程1触发了线程3(计算[1,2])和线程4
线程2触发了线程5和线程3(在完成计算[8,9,10]之后计算[1,2])
据我了解,线程3处理线程1和线程2的工作。
看起来像线程3 工作偷
如果我将其更改为

 ExecutorService executorService = Executors.newWorkStealingPool();

它支持工作教学算法,我有什么不同看法?

[main] DEBUG com.example.CustomCallable -  start [[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]  
[ForkJoinPool-1-worker-1] DEBUG com.example.CustomCallable -  start [[1, 2, 3, 4, 5]]  
[ForkJoinPool-1-worker-2] DEBUG com.example.CustomCallable -  start [[1, 2]]  
[ForkJoinPool-1-worker-2] DEBUG com.example.CustomCallable -  sum[[1, 2]]=3  
[ForkJoinPool-1-worker-2] DEBUG com.example.CustomCallable -  start [[3, 4, 5]]  
[ForkJoinPool-1-worker-3] DEBUG com.example.CustomCallable -  start [[6, 7, 8, 9, 10]]  
[ForkJoinPool-1-worker-0] DEBUG com.example.CustomCallable -  start [[6, 7]]  
[ForkJoinPool-1-worker-0] DEBUG com.example.CustomCallable -  sum[[6, 7]]=13  
[ForkJoinPool-1-worker-0] DEBUG com.example.CustomCallable -  start [[8, 9, 10]]  
**[ForkJoinPool-1-worker-4] DEBUG com.example.CustomCallable -  start [[3]]**  
**[ForkJoinPool-1-worker-4] DEBUG com.example.CustomCallable -  sum[[3]]=3**  
[ForkJoinPool-1-worker-4] DEBUG com.example.CustomCallable -  start [[4, 5]]  
[ForkJoinPool-1-worker-4] DEBUG com.example.CustomCallable -  sum[[4, 5]]=9  
**[ForkJoinPool-1-worker-4] DEBUG com.example.CustomCallable -  start [[8]]**  
**[ForkJoinPool-1-worker-4] DEBUG com.example.CustomCallable -  sum[[8]]=8**  
[ForkJoinPool-1-worker-4] DEBUG com.example.CustomCallable -  start [[9, 10]]  
[ForkJoinPool-1-worker-4] DEBUG com.example.CustomCallable -  sum[[9, 10]]=19  
[ForkJoinPool-1-worker-2] DEBUG com.example.CustomCallable -  sum[[3, 4, 5]]=12  
[ForkJoinPool-1-worker-0] DEBUG com.example.CustomCallable -  sum[[8, 9, 10]]=27  
[ForkJoinPool-1-worker-1] DEBUG com.example.CustomCallable -  sum[[1, 2, 3, 4, 5]]=15  
[ForkJoinPool-1-worker-3] DEBUG com.example.CustomCallable -  sum[[6, 7, 8, 9, 10]]=40  
[main] DEBUG com.example.CustomCallable -  sum[[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]]=55


您可以看到我们有5个工作人员,而工作人员4处理由工作人员3和工作人员1触发的工作。与以前的执行有何不同?

您可以从github

下载代码

0 个答案:

没有答案