1,给定并行级别:

  • 1,ExecutorService newWorkStealingPool(int parallelism): 创建持有足够的线程的线程池来支持给定的并行级别,该方法还会使用多个队列来减少竞争
  • 2,ExecutorService newWorkStealingPool(): 该方法是前面方法的简化版本 如果前机器有4个CPU,则目标并行级别被设置为4
这两个方法是Java8新增的,这两个方法可充分利用多 CPU 并行的能力 这两个方法生成的 work stealing 池,都相于后台线程池,如果所有的前台线程都死亡了workstealing 池中的线程会自动死亡。
用法:
  1. 通过Executors.newWorkStealingPool()静态方法获取ExecutorService类对象
  2. 使用ExecutorService对象.submit(Runnable runnable)提交runnable 或Callable 接口类实现的任务对象
 示例代码:
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类或RecursiveTask类(可以有返回值)实现其抽象方法compute;方法中自调用创建子任务对象.fork()方法提交拆分任务
  2. 用自定义任务类,实例化可拆分任务对象;子任务类的join()方法获取返回值
  3. 使用ForkJoinPool实例化对象,submit可拆分任务对象;返回ForkJoinTask对象
  4. ForkJoinPool对象awaitTermination执行任务(无返回值);。
  5. 使用ForkJoinTask对象对象.get()方法获取返回值

无返回值示例代码(RecursiveAction类任务):

要求:给出一个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();
}
}

 有返回值示例代码(RecursiveTask类任务):

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

import java.util.concurrent.*;

/**
* @ClassName MyRecursiveAction
* @projectName: object1
* @author: Zhangmingda
* @description: XXX
* date: 2021/4/27.
*/
public class ForkJoinPoolRecursiveTasksReturnExample {
/**
* 定义一个支持拆分计算的任务
*/
private static class CalcNumCountTaskRecursiveTask extends RecursiveTask<Integer> {
private int start;
private int end;
private final int MAXNUM = 30; /**
* 构造实例传入任务需要的参数
*/
public CalcNumCountTaskRecursiveTask(int start, int end) {
this.start = start;
this.end = end;
} /**
* 具体执行计算的任务的抽象方法重写
*/
@Override
protected Integer compute() {
String tName = Thread.currentThread().getName();
Integer count = 0;
if ((end - start) < MAXNUM){
System.out.println("start:" + start);
System.out.println("end:" + end);
for (int i=start; i<end; i++){
count+=i;
}
return count;
}else {
int middle = (start + end) /2;
/**
* 大任务拆分为两个小任务,
*/
CalcNumCountTaskRecursiveTask subTask1 = new CalcNumCountTaskRecursiveTask(start,middle);
CalcNumCountTaskRecursiveTask subTask2 = new CalcNumCountTaskRecursiveTask(middle,end);
//分别执行两个小任务
subTask1.fork();subTask2.fork();
return subTask1.join() + subTask2.join();
}
}
} /**
执行计算任务
*/
public static void main(String[] args) throws InterruptedException, ExecutionException {
ForkJoinPool forkJoinPool = new ForkJoinPool();
CalcNumCountTaskRecursiveTask calcCountTask = new CalcNumCountTaskRecursiveTask(1,101);
//线程池提交任务
ForkJoinTask<Integer> forkJoinTask = forkJoinPool.submit(calcCountTask);
//获取执行结果
System.out.println(forkJoinTask.get());;
//关闭提交接口
forkJoinPool.shutdown();
}
}

java 多线程 线程池:多核CPU利用ExecutorService newWorkStealingPool; ForkJoinPool线程池 执行可拆分的任务RecursiveAction;RecursiveTask的更多相关文章

  1. “全栈2019”Java多线程第三十五章:如何获取线程被等待的时间?

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  2. “全栈2019”Java多线程第二十五章:生产者与消费者线程详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...

  3. java多线程并发编程与CPU时钟分配小议

    我们先来研究下JAVA的多线程的并发编程和CPU时钟振荡的关系吧 老规矩,先科普 我们的操作系统在DOS以前都是单任务的 什么是单任务呢?就是一次只能做一件事 你复制文件的时候,就不能重命名了 那么现 ...

  4. “全栈2019”Java多线程第三十六章:如何设置线程的等待截止时间

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 下一章 "全栈2019"J ...

  5. 多核CPU利用测试

      一直在想程序上是否特意让线程在指定的CPU上去运行,这样可以提高运行效率,所以特地写个代码让CPU使用率画正弦曲线的实验,我使用的是AMD X4 641的CPU,为四核四线程的片子. 代码如下 # ...

  6. java——多线程的实现方式、三种办法解决线程赛跑、多线程数据同步(synchronized)、死锁

    多线程的实现方式:demo1.demo2 demo1:继承Thread类,重写run()方法 package thread_test; public class ThreadDemo1 extends ...

  7. Java多线程和并发(一),进程与线程的区别

    目录 1.进程和线程的由来 2.进程和线程的定义 3.进程和线程的区别 一.进程和线程的区别 1.进程和线程的由来 2.进程和线程的定义 进程是资源分配的最小单位,线程是CPU调度的最小单位 3.进程 ...

  8. 二、java多线程编程核心技术之(笔记)——如何停止线程?

    1.异常法 public class MyThread extends Thread { @Override public void run() { super.run(); try { for (i ...

  9. Java多线程01(Thread类、线程创建、线程池)

    Java多线程(Thread类.线程创建.线程池) 第一章 多线程 1.1 多线程介绍 1.1.1 基本概念 进程:进程指正在运行的程序.确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于 ...

随机推荐

  1. java8两个字段进行排序问题

    //这个解决问题 Comparator<Anjianxinxi> getLianriqi = Comparator.comparing(Anjianxinxi::getLianriqi). ...

  2. postman自动调用获取token

    Postman不光支持单次请求,还支持环境变量.全局变量.集合变量 本文使用Collection Variable Collection 如下图可以点击Collection然后可以添加请求和文件夹,以 ...

  3. 面渣逆袭:HashMap追魂二十三问

    大家好,我是老三. HashMap作为我们熟悉的一种集合,可以说是面试必考题.简单的使用,再到原理.数据结构,还可以延伸到并发,可以说,就一个HashMap,能聊半个小时. 1.能说一下HashMap ...

  4. UOJ #76 -【UR #6】懒癌(思维题)

    UOJ 题面传送门 神仙题. orz czx,czxyyds 首先没有懒癌的狗肯定不会被枪毙,证明显然. 接下来考虑怎样计算一种局面的答案,假设 \(dp_S\) 表示对于有且仅有 \(S\) 中的狗 ...

  5. 洛谷 P6189 - [NOI Online #1 入门组]跑步(根号分治+背包)

    题面传送门 题意: 求有多少个数列 \(x\) 满足: \(\sum x_i=n\) \(x_i\geq x_{i+1}\) 答案对 \(p\) 取模. ...你确定这叫"入门"组 ...

  6. Linux-普通用户和root用户任意切换

    普通用户切换为root: 1.[xnlay@bogon ~]$含义:xnlay代表当前用户,bogon指的是主机名,~表示当前用户,$表示普通用户:[root@bogon ~]#root代表是超级用户 ...

  7. .Net Core——用SignalR撸个游戏

    之前开内部培训,说到实时web应用这一块讲到了SignalR,我说找时间用它做个游戏玩玩,后面时间紧张就一直没安排.这两天闲了又想起这个事,考虑后决定用2天时间写个斗D主,安排了前端同学写客户端,我写 ...

  8. linux系统中安装JDK

    安装之前的准备工作 查看系统中之前安装好的JDK java –version rpm -qa | grep java 卸载JDK (以java-1.7.0-openjdk-1.7.0.45-2.4.3 ...

  9. 日常Java 2021/11/18

    用idea实现Javaweb登录页面 <%-- Created by IntelliJ IDEA. User: Tefuir Date: 2021/11/18 Time: 18:14 To ch ...

  10. day13 装饰器与语法糖

    day13 装饰器与语法糖 一.装饰器 1.什么是装饰器 装饰器就是装饰别人的工具,具体是指为被装饰者添加新功能 装饰器->函数 被装饰者->函数 2.为何要用装饰器 装饰器的核心思想:( ...