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 基本概念 进程:进程指正在运行的程序.确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于 ...
随机推荐
- 多线程03.实现Runnable接口
package chapter2; public class TicketWindowRun implements Runnable { private static final int MAX =5 ...
- Python之浏览器的前进或后退
import webbrowserwebbrowser.back() 后退webbrowser.forward() 前进
- Promise(resolve,reject)的基本使用
什么是Promise? Promise是一个构造函数,其原型上有 then.catch方法,还有reslove,reject等静态方法.通过创建Promise实例,可以调用Promise.protot ...
- 【.NET 6】使用.NET 6开发minimal api以及依赖注入的实现、VS2022热重载和自动反编译功能的演示
前言: .net 6 LTS版本发布已经有若干天了.此处做一个关于使用.net 6 开发精简版webapi(minimal api)的入门教程,以及VS2022 上面的两个强大的新技能(热重载.代码自 ...
- CF1418G Three Occurrences
统计满足某些性质的区间个数. 我们考虑移动 \(r\) 指针. 然后考虑把不能选的区间 \(ban\)掉. 具体看下细节吧. #include<iostream> #include< ...
- 洛谷 P7718 -「EZEC-10」Equalization(差分转化+状压 dp)
洛谷题面传送门 一道挺有意思的题,现场切掉还是挺有成就感的. 首先看到区间操作我们可以想到差分转换,将区间操作转化为差分序列上的一个或两个单点操作,具体来说我们设 \(b_i=a_{i+1}-a_i\ ...
- 『学了就忘』Linux文件系统管理 — 61、使用parted命令进行分区
目录 1.parted命令介绍 2.parted交互模式 3.建立分区 (1)查看分区 (2)修改成GPT分区表 (3)建立分区 (4)建立文件系统(格式化) (5)调整分区大小 (6)删除分区 1. ...
- mysql 计算日期为当年第几季度
select T21620.日期 as F21634, QUARTER('98-04-01') as quarter #返回日期是一年的第几个季度 - ...
- Demo01无重复数字
package 习题集2;//有1,2,3,4四个数字,能组成多少个互不相同且无重复数字的三位数?都是多少?public class Demo1 { public static void main(S ...
- 学习java 6.30
学习内容:Java的运算符与C中类似,虽是类似,还是有点区别,在这里详细说明一下,即字符以及字符串的+操作,字符的+操作执行后需要赋值给表达式中数据范围最大的类型, 字符串的+操作,当+中有字符串,则 ...