java 多线程 线程池:多核CPU利用ExecutorService newWorkStealingPool; ForkJoinPool线程池 执行可拆分的任务RecursiveAction;RecursiveTask
1,给定并行级别:
- 1,ExecutorService newWorkStealingPool(int parallelism): 创建持有足够的线程的线程池来支持给定的并行级别,该方法还会使用多个队列来减少竞争
- 2,ExecutorService newWorkStealingPool(): 该方法是前面方法的简化版本 如果前机器有4个CPU,则目标并行级别被设置为4
- 通过Executors.newWorkStealingPool()静态方法获取ExecutorService类对象
- 使用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 用于拆分大的计算任务,拆分为多个小的计算任务
用法:
- 定义可以拆分的任务类,继承RecursiveAction类或RecursiveTask类(可以有返回值)实现其抽象方法compute;方法中自调用创建子任务对象.fork()方法提交拆分任务
- 用自定义任务类,实例化可拆分任务对象;子任务类的join()方法获取返回值
- 使用ForkJoinPool实例化对象,submit可拆分任务对象;返回ForkJoinTask对象
- ForkJoinPool对象awaitTermination执行任务(无返回值);。
- 使用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的更多相关文章
- “全栈2019”Java多线程第三十五章:如何获取线程被等待的时间?
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- “全栈2019”Java多线程第二十五章:生产者与消费者线程详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java多 ...
- java多线程并发编程与CPU时钟分配小议
我们先来研究下JAVA的多线程的并发编程和CPU时钟振荡的关系吧 老规矩,先科普 我们的操作系统在DOS以前都是单任务的 什么是单任务呢?就是一次只能做一件事 你复制文件的时候,就不能重命名了 那么现 ...
- “全栈2019”Java多线程第三十六章:如何设置线程的等待截止时间
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 下一章 "全栈2019"J ...
- 多核CPU利用测试
一直在想程序上是否特意让线程在指定的CPU上去运行,这样可以提高运行效率,所以特地写个代码让CPU使用率画正弦曲线的实验,我使用的是AMD X4 641的CPU,为四核四线程的片子. 代码如下 # ...
- java——多线程的实现方式、三种办法解决线程赛跑、多线程数据同步(synchronized)、死锁
多线程的实现方式:demo1.demo2 demo1:继承Thread类,重写run()方法 package thread_test; public class ThreadDemo1 extends ...
- Java多线程和并发(一),进程与线程的区别
目录 1.进程和线程的由来 2.进程和线程的定义 3.进程和线程的区别 一.进程和线程的区别 1.进程和线程的由来 2.进程和线程的定义 进程是资源分配的最小单位,线程是CPU调度的最小单位 3.进程 ...
- 二、java多线程编程核心技术之(笔记)——如何停止线程?
1.异常法 public class MyThread extends Thread { @Override public void run() { super.run(); try { for (i ...
- Java多线程01(Thread类、线程创建、线程池)
Java多线程(Thread类.线程创建.线程池) 第一章 多线程 1.1 多线程介绍 1.1.1 基本概念 进程:进程指正在运行的程序.确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于 ...
随机推荐
- pycharm的selenium设置
如果运行文件,提示 no model named selenium 那就需要添加selenium的安装地址 如上图 在python>lib>site-packages 在pycharm的f ...
- UOJ 75 - 【UR #6】智商锁(矩阵树定理+随机+meet-in-the-middle)
题面传送门 一道很神的矩阵树定理+乱搞的题 %%%%%%%%%%%%%%% vfk yyds u1s1 这种题目我是根本想不出来/kk,大概也就 jgh 这样的随机化带师才能想到出来吧 首先看到生成树 ...
- Codeforces 587F - Duff is Mad(根号分治+AC 自动机+树状数组)
题面传送门 第一眼看成了 CF547E-- 话说 CF587F 和 CF547E 出题人一样欸--还有另一道 AC 自动机的题 CF696D 也是这位名叫 PrinceOfPersia 的出题人出的- ...
- Parallel NetCDF 简介
Parallel NetCDF API 所有C接口前加ncmpi前缀,Fortran接口前加nfmpi前缀 函数返回整数 NetCDF 状态变量 1. Variable and Parameter T ...
- BSA分析
目录 两种算法 1. 欧氏距离(ED)算法 2. SNP-index算法 实操 1. 上游分析 2. 下游分析 两种算法 1. 欧氏距离(ED)算法 mut与wt分别代表突变型混池.野生型混池,A.C ...
- R语言与医学统计图形【3】条形图、误差图
R语言基础绘图系统 基础图形--条形图.误差图 3.条形图 barplot接收的数据是矩阵而非数据框. data <- sample(c(50:80),5) barplot(data,col=h ...
- 多人协作解决方案,git flow的使用
简介 Gitflow工作流程围绕项目发布定义了严格的分支模型. 为不同的分支分配了非常明确的角色,并且定义了使用场景和用法.除了用于功能开发的分支,它还使用独立的分支进行发布前的准备.记录以及后期维护 ...
- jQuery无限载入瀑布流 【转载】
转载至 http://wuyuans.com/2013/08/jquery-masonry-infinite-scroll/ jQuery无限载入瀑布流 好久没更新日志了,一来我比较懒,二来最近也比较 ...
- Linux网络管理(一)之配置主机名与域名
Linux网络管理(一)之配置主机名与域名参考自:[1]修改主机名(/etc/hostname和/etc/hosts区别) https://blog.csdn.net/shmily_lsl/artic ...
- centos 7 重新获取IP地址
1.安装软件包 dhclient # yum install dhclient 2.释放现有IP # dhclient -r 3.重新获取 # dhclient 4.查看获取到到IP # ip a