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 基本概念 进程:进程指正在运行的程序.确切的来说,当一个程序进入内存运行,即变成一个进程,进程是处于 ...
随机推荐
- 解决Windows7、Windows10 ping不通的问题
在VLAN交换机网络下面不能访问Windows10或者Windows7共享.ping不通问题,关闭防火墙发现能ping通了共享也正常了. 但是关闭防火墙将给电脑系统留下安全隐患.不怕麻烦的可以继续往下 ...
- 爬虫——正则表达式爬取豆瓣电影TOP前250的中英文名
正则表达式爬取豆瓣电影TOP前250的中英文名 1.首先要实现网页的数据的爬取.新建test.py文件 test.py 1 import requests 2 3 def get_Html_text( ...
- 7.2 k8s 基于PV、PVC搭建zookeeper 3节点集群
1.PV,PVC介绍 1.1.StorageClass & PV & PVC关系图 Volumes 是最基础的存储抽象,其支持多种类型,包括本地存储.NFS.FC以及众多的云存储,我们 ...
- c语言实参与形参的区别
1 #include<stdio.h> 2 #include<math.h> 3 4 /** 5 * 形参和实参的功能是作数据传送. 6 * 函数调用中发生的数据传送是单向的. ...
- Atcoder Regular Contest 117 D - Miracle Tree(分析性质+构造)
Atcoder 题面传送门 笑死,阴间语文作业到现在还没写完,为了在这个点保持精神,我只好来颓篇题解辣 我们考虑探究一下怎么最小化 \(\max\limits_{i=1}^nE_i\),我们假设 \( ...
- Git常用操作(二)
仓库拉取 git clone XXX 修改仓库链接 $ git config -l # 显示coding列表 $ git config --get remote.origin.url # 返回orig ...
- Genscan指南
Genscan指南 GenScan是一个gene识别软件,主要是通过已知生物的基因结构特征来识别新的基因(parse).所利用的基因特征请参看readme文件. 特点: 只考虑编码蛋白的基因. 模型考 ...
- js变量作为数组对象的键值方法
js变量作为数组对象的键值方法,变量键值获取数组值 js也可以像php的数组一样用下标获取数组的值,方法是: var arr = {'key':'abc'}; var key = 'key'; con ...
- Hive(一)【基本概念、安装】
目录 一. Hive基本概念 1.1 Hive是什么 1.2 Hive的优缺点 1.3 Hive的架构 1.4 Hive和数据库的区别 二. Hive安装 2.1 安装地址 2.2 Mysql的安装 ...
- Output of C++ Program | Set 13
Predict the output of following C++ program. 1 #include<iostream> 2 using namespace std; 3 4 c ...