首页 > 编程语言 > 详细

java 多线程 线程池:多核CPU利用ExecutorService newWorkStealingPool; ForkJoinPool线程池 执行可拆分的任务RecursiveAction

时间:2021-04-27 20:02:40      阅读:57      评论:0      收藏:0      [点我收藏+]

1,给定并行级别:

  • 1,ExecutorService newWorkStealingPool(int parallelism): 创建持有足够的线程的线程池来支持给定的并行级别,该方法还会使用多个队列来减少竞争
  • 2,ExecutorService newWorkStealingPool(): 该方法是前面方法的简化版本 如果前机器有4个CPU,则目标并行级别被设置为4
  • 这两个方法是Java8新增的,这两个方法可充分利用多 CPU 并行的能力 这两个方法生成的 work stealing 池,都相于后台线程池,如果所有的前台线程都死亡了workstealing 池中的线程会自动死亡。
这两个方法是Java8新增的,这两个方法可充分利用多 CPU 并行的能力 这两个方法生成的 work stealing 池,都相于后台线程池,如果所有的前台线程都死亡了workstealing 池中的线程会自动死亡。
 示例代码:
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @ClassName ExecutorsWorkStealingPoolTest
 * @projectName: object1
 * @author: Zhangmingda
 * @description: XXX
 * date: 2021/4/27.
 */
public class ExecutorsWorkStealingPoolTest {
    public static void main(String[] args) throws InterruptedException {
        Runnable r = () -> {
            String tName = Thread.currentThread().getName();
            try {
                System.out.println(tName + "开始运行");
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(tName + "运行结束");
        };
        /**
         * 创建支持多核CPU并行的线程池
         */
        ExecutorService executorService = Executors.newWorkStealingPool(); //译文:Stealing 窃取
        for (int i=0; i<10; i++){
            executorService.submit(r);
        }
        System.out.println(Runtime.getRuntime().availableProcessors()); //CPU核心数
        Thread.sleep(3000);
    }
}

技术分享图片

 

 2、Java8 增强的 ForkJoinPool 用于拆分大的计算任务,拆分为多个小的计算任务

为了充分利用CPU、多核CPU的性能优势,计算机软件系统应该可以充分"挖掘"每个CPU的计算能力,绝不能让某个CPU处于"空闲"状态,为了充分利用多CPU、多核CPU的优势,可以考虑把一个任务拆分成多个"小任务",把多个"小任务"放到多个处理器核上并行执行;当多个"小任务"执行完成之后,再将这些执行结果合并起来即可。ForkJoinPool非常适合做密集计算型的任务

用法:

  1. 定义可以拆分的任务类,继承RecursiveAction类,实现其抽象方法compute;
  2. 用自定义任务类,实例化可拆分任务对象;
  3. 使用ForkJoinPool实例化对象,submit可拆分任务对象;
  4. ForkJoinPool对象awaitTermination执行任务。
  5. 使用ForkJoinPool实例化对象.get()方法获取返回值

无返回值示例代码:

要求:给出一个int数据范围,范围内整数个数>100 则拆分不同的线程来打印。每个线程只打印不超过100个整数。

import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;
import java.util.concurrent.TimeUnit;

/**
 * @ClassName MyRecursiveAction
 * @projectName: object1
 * @author: Zhangmingda
 * @description: XXX
 * date: 2021/4/27.
 */
public class MyRecursiveAction {
    /**
     * 定义一个支持拆分计算的任务
     */
    private static class PrintTaskRecursiveAction extends RecursiveAction{
        private int start;
        private int end;
        private final int MAXNUM = 100;

        /**
         * 构造实例传入任务需要的参数
         */
        public PrintTaskRecursiveAction(int start, int end) {
            this.start = start;
            this.end = end;
        }

        /**
         * 具体执行计算的任务的抽象方法重写
         */
        @Override
        protected void compute() {
            String tName = Thread.currentThread().getName();
            if ((end - start) < MAXNUM){
                System.out.println(tName + "    start:" + start);
                System.out.println(tName + "    end:" + end);
            }else {
                int middle = (start + end) /2;
                /**
                 * 大任务拆分为两个小任务,
                 */
                PrintTaskRecursiveAction subTask1 = new PrintTaskRecursiveAction(start,middle);
                PrintTaskRecursiveAction subTask2 = new PrintTaskRecursiveAction(middle,end);
                //分别执行两个小任务
                subTask1.fork();subTask2.fork();
            }
        }
    }

    /**
     执行计算任务
     */
    public static void main(String[] args) throws InterruptedException {
        ForkJoinPool forkJoinPool = new ForkJoinPool();
        PrintTaskRecursiveAction printTask = new PrintTaskRecursiveAction(1,300);
        //线程池提交任务
        forkJoinPool.submit(printTask);
        forkJoinPool.awaitTermination(1, TimeUnit.SECONDS);
        //关闭提交接口
        forkJoinPool.shutdown();
    }
}

技术分享图片

 

 有返回值示例代码:

要求:计算1~100的和,每个线程计算不超过10个数的和。

 

java 多线程 线程池:多核CPU利用ExecutorService newWorkStealingPool; ForkJoinPool线程池 执行可拆分的任务RecursiveAction

原文:https://www.cnblogs.com/zhangmingda/p/14710284.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!