[关闭]
@boothsun 2018-03-10T17:40:16.000000Z 字数 1967 阅读 1657

Fork/Join框架(非重点内容 未完待续)

Java多线程


Fork/Join框架是Java 7 提供的一个用于并行执行任务的框架,是一个把大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务结果的框架。

image.png-165.6kB

工作窃取算法

工作窃取(work-stealing)算法是指某个线程从其他队列里窃取任务来执行。那么,为什么需要使用工作窃取算法呢?假如我们需要做一个比较大的任务,可以把这个任务分割为若干互不依赖的子任务,为了减少线程间的竞争,把这些子任务分别放到不同的队列里,并为每个队列创建一个单独的线程来执行队列里的任务,线程和队列一一对应。比如A线程负责处理A队列里的任务。但是,有的线程会先把自己队列里的任务干完,而其他线程对应的队列里还有任务等待处理。干完活的线程与其等着,不如去帮其他线程干活,于是它就去其他线程的队列里窃取一个任务来执行。而在这时它们会访问同一个队列,所以为了减少窃取任务线程和被窃取任务线程之间的竞争,通常会使用双端队列,被窃取任务线程永远从双端队列的头部拿任务执行,而窃取任务的线程永远从双端队列的尾部拿任务执行。

工作窃取的运行流程下图所示:
image.png-81.2kB

工作窃取算法的优点:

工作窃取算法的缺点:

Fork/Join常用API

ForkJoinPool

ForkJoinPool是ForkJoin框架中的任务调度器,和ThreadPoolExecutor一样实现了自己的线程池,提供了三种调度子任务的方法:

ForkJoinTask

我们要使用ForkJoin框架,必须首先创建一个ForkJoin任务。它提供在任务中执行fork()和join()操作的机制。通常情况下,我们不需要直接继承ForkJoinTask类,只需要继承它的子类,Fork/Join框架提供了以下两个子类。

Fork/Join 使用案例

  1. public class ForkJoinTest extends RecursiveTask<Long> {
  2. private static final long MAX = 1000000000L;
  3. private static final long THRESHOLD = 1000L;
  4. private long start;
  5. private long end;
  6. public ForkJoinTest(long start, long end) {
  7. this.start = start;
  8. this.end = end;
  9. }
  10. public static void main(String[] args) throws Exception{
  11. System.out.println("--------------------");
  12. Thread.sleep(10 * 1000L);
  13. testForkJoin();
  14. }
  15. private static void testForkJoin() {
  16. System.out.println("testForkJoin");
  17. long start = System.currentTimeMillis();
  18. ForkJoinPool forkJoinPool = new ForkJoinPool();
  19. Long sum = forkJoinPool.invoke(new ForkJoinTest(1, MAX));
  20. System.out.println(sum);
  21. System.out.println(System.currentTimeMillis() - start + "ms");
  22. }
  23. @Override
  24. protected Long compute() {
  25. long sum = 0;
  26. if (end - start <= THRESHOLD) {
  27. for (long i = start; i <= end; i++) {
  28. sum += i;
  29. }
  30. return sum;
  31. } else {
  32. long mid = (start + end) / 2;
  33. ForkJoinTest task1 = new ForkJoinTest(start, mid);
  34. ForkJoinTest task2 = new ForkJoinTest(mid + 1, end);
  35. invokeAll(task1,task2);
  36. return task1.join() + task2.join();
  37. }
  38. }
  39. }

网文关于正确使用Fork/JOIN框架:

Java的Fork/Join任务,你写对了吗?

Fork/Join 实现原理

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注