关于这个算法,我读了很多东西。在解释此算法时,单词: 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
下载代码