[并发编程]并发编程第二篇:利用并发编程,实现计算大量数据的和
利用并发编程,实现计算大量数据的和
实现代码:
package tj.pojo.generate.main;import java.util.ArrayList; import java.util.List; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Future; import java.util.concurrent.FutureTask;public class ConcurrentCalculator {private ExecutorService exec;private int cpuCoreNumber;private List<Future<Long>> tasks = new ArrayList<Future<Long>>();// 内部类class SumCalculator implements Callable<Long> {private int[] numbers;private int start;private int end;public SumCalculator(final int[] numbers, int start, int end) {this.numbers = numbers;this.start = start;this.end = end;}@Overridepublic Long call() throws Exception {Long sum = 0L;for (int i = start; i < end; i++) {sum += numbers[i];}System.out.println(String.format("%s~%s的和为%s", start, end, sum));return sum;}}public ConcurrentCalculator() {cpuCoreNumber = Runtime.getRuntime().availableProcessors();System.out.println("CPU核心数:" + cpuCoreNumber);exec = Executors.newFixedThreadPool(cpuCoreNumber);}public Long sum(final int[] numbers) {for (int i = 0; i < cpuCoreNumber; i++) {int increment = numbers.length / cpuCoreNumber + 1;int start = increment * i;int end = start + increment;if (end > numbers.length) {end = numbers.length;}SumCalculator task = new SumCalculator(numbers, start, end);FutureTask<Long> future = new FutureTask<Long>(task);tasks.add(future);System.out.println("添加一个任务,总任务数为:" + tasks.size());if (!exec.isShutdown()) {exec.submit(future);// ExecutoreService提供了submit()方法,传递一个Callable,或Runnable,返回Future。// exec.submit(task); }}System.out.println("任务分配完成,总任务数为:" + tasks.size());return getResult();}public Long getResult() {Long sums = 0L;for (Future<Long> task : tasks) {try {Long sum = task.get();sums += sum;System.out.println("当前总合计:" + sums);} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}}return sums;}public void close() {exec.shutdown();} }
其中,在代码的第62行~第64行,由于不了解ExecutoreService.submit(Runnable task)方法的功能。
同时FutureTask<Long> future和SumCalculator task都实现了Runnable接口,造成代码调用时,进程一直不结束。
传递了FutureTask<Long> future才正确执行。
exec.submit(future);// ExecutoreService提供了submit()方法,传递一个Callable,或Runnable,返回Future。// exec.submit(task);
测试方法:
public static void test() {int[] numbers = new int[100];for (int i = 0; i < 100; i++) {numbers[i] = i + 1;}tj.pojo.generate.main.ConcurrentCalculator cc = new tj.pojo.generate.main.ConcurrentCalculator();Long sum = cc.sum(numbers);System.out.println("1~100的和为" + sum);cc.close();}
FutureTask的实现代码:
public class FutureTask<V> implements RunnableFuture<V>
FutureTask类实现了RunnableFuture接口,RunnableFuture接口的实现代码:
public interface RunnableFuture<V> extends Runnable, Future<V> {
void run();
}
可以看出RunnableFuture继承了Runnable接口和Future接口,而FutureTask实现了RunnableFuture接口。
所以它既可以作为Runnable被线程执行,又可以作为Future得到Callable的返回值。
事实上,FutureTask是Future接口的一个唯一实现类。
并发编程的两种实现形式:
1):使用Callable+Future获取执行结果
public class Test {public static void main(String[] args) {ExecutorService executor = Executors.newCachedThreadPool();Task task = new Task();Future<Integer> result = executor.submit(task);executor.shutdown();try {Thread.sleep(1000);} catch (InterruptedException e1) {e1.printStackTrace();}System.out.println("主线程在执行任务");try {System.out.println("task运行结果"+result.get());} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}System.out.println("所有任务执行完毕");} } class Task implements Callable<Integer>{@Overridepublic Integer call() throws Exception {System.out.println("子线程在进行计算");Thread.sleep(3000);int sum = 0;for(int i=0;i<100;i++)sum += i;return sum;} }
2):使用Callable+FutureTask获取执行结果
public class Test {public static void main(String[] args) {//第一种方式ExecutorService executor = Executors.newCachedThreadPool();Task task = new Task();FutureTask<Integer> futureTask = new FutureTask<Integer>(task);executor.submit(futureTask);executor.shutdown();//第二种方式,注意这种方式和第一种方式效果是类似的,只不过一个使用的是ExecutorService,一个使用的是Thread/*Task task = new Task();FutureTask<Integer> futureTask = new FutureTask<Integer>(task);Thread thread = new Thread(futureTask);thread.start();*/try {Thread.sleep(1000);} catch (InterruptedException e1) {e1.printStackTrace();}System.out.println("主线程在执行任务");try {System.out.println("task运行结果"+futureTask.get());} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}System.out.println("所有任务执行完毕");} } class Task implements Callable<Integer>{@Overridepublic Integer call() throws Exception {System.out.println("子线程在进行计算");Thread.sleep(3000);int sum = 0;for(int i=0;i<100;i++)sum += i;return sum;} }
转载于:https://www.cnblogs.com/Candies/p/5692389.html
[并发编程]并发编程第二篇:利用并发编程,实现计算大量数据的和相关推荐
- 【编程实践】第二章 C++面向对象编程《C++程序设计语言》 / By 禅与计算机程序设计艺术ChatGPT
[编程实践]第二章 C++面向对象编程<C++程序设计语言> / By 禅与计算机程序设计艺术&ChatGPT 第二章 C++面向对象编程 在C++中,面向对象编程主要通过类和对象 ...
- Python高级网络编程系列之第二篇
在上一篇中,我们深入探讨了TCP/IP协议的11种状态,理解这些状态对我们编写服务器的时候有很大的帮助,但一般写服务器都是使用C/Java语言,因为这些语言对高并发的支持特别好.我们写的这些简单的服务 ...
- [转]12篇学通C#网络编程——第二篇 HTTP应用编程(上)
本文转自:http://www.cnblogs.com/huangxincheng/archive/2012/01/09/2316745.html 我们学习网络编程最熟悉的莫过于Http,好,我们就从 ...
- python的socket编程执行顺序_Python篇-Socket网络编程
TZ:多读英文,少点烦躁 一 : 科普一分钟 简单来说Socket就是对TCP/IP等网络协议的封装和应用,其重要的两个动作就是发送和接受当我们需要调用网络连接时只需建立Socket连接,Socket ...
- windows系统重装(安装)第二篇——利用老毛桃本地PE系统重装工具重装系统
如果不知道怎么制作PE环境的,请看第一篇-------->>>>>>windows系统重装(安装)第一篇--老毛桃本地PE环境的安装 此教程主要讲解怎么在PE环境下 ...
- android 串口开发第二篇:利用jni实现android和串口通信
一:串口通信简介 由于串口开发涉及到jni,所以开发环境需要支持ndk开发,如果未配置ndk配置的朋友,或者对jni不熟悉的朋友,请查看上一篇文章,android 串口开发第一篇:搭建ndk开发环境以 ...
- matlab矩阵转入tecplot,利用Tecplot导入MATLAB计算结果数据进行三维可视化
前言 对于(坐标,物理量)这类数据的可视化(云图)一直在探索,二维数据选择用matlab处理,因为matlab的imagesc函数可以根据数据值的大小用不同颜色来显示.但是对应的三维数据(x,y,z, ...
- 利用Tecplot导入MATLAB计算结果数据进行三维可视化
前言 对于(坐标,物理量)这类数据的可视化(云图)一直在探索,二维数据选择用matlab处理,因为matlab的imagesc函数可以根据数据值的大小用不同颜色来显示.但是对应的三维数据(x,y,z, ...
- 利用Excel VBA批量计算气象数据多个台站多年来春季和冬季降水量和平均气温
气象数据是地理数据的重要组成部分,存储量虽然不大,但是处理过程非常繁琐,长时序数据更不用说.本文总结了一个气象数据的基本处理方法. 如下图所示,气象数据的排列格式是区站号→年→月→降水量→平均气温,时 ...
- hive编程指南电子版_第三篇|Spark SQL编程指南
在<第二篇|Spark Core编程指南>一文中,对Spark的核心模块进行了讲解.本文将讨论Spark的另外一个重要模块--Spark SQL,Spark SQL是在Shark的基础之上 ...
最新文章
- 娱乐百分百-20090318 星光四班 - 健康程序员,至尚生活!
- 005_FastDFS分布式nginx访问
- struts1.3执行流程分析
- Windows Live Messenger 2011,离线安装、多开、去广告……
- 使用jQuery加载js脚本
- 数字信号 fft c源码_如何制作一个简单的人体动态识别微信小程序(附源码)
- Unix整理笔记——在指定时间运行程序——里程碑M12
- java连接zookeeper服务器出现“KeeperErrorCode = ConnectionLoss for ...”
- MySQL错误号码1862:your password has expired
- 大学生创业如何选择一个不错的创业新项目?
- AVOD、SVOD、TVOD、PVOD:视频点播商业模式
- [源码]vb6鼠标连点器
- mysql索引一般什么数据结构_mysql索引一般使用什么数据结构
- 1.java基础 jdk,jre,jvm作业 - 答案(jdk,jre,jvm)
- FireFox火狐浏览器配置页面about:config参数说明
- app式成语_app式的词语,app的成语都有什么?
- curl指定代理_如何使用cURL指定用户代理
- “开宝五子棋读谱”软件的隐私政策和权限说明
- 博士申请 | 港中深韩晓光课题组招收与华为中央媒体院联合培养博士生
- 博客中的动态图片如何制作
热门文章
- L1相对于L2较稀疏的原因
- 程序员绩效总结_阿里五年晋升三次,这个程序员要聊聊他的选择
- android内核编译 me525,摩托罗拉DEFY(ME525)刷Android 2.3.4变砖后的解决方法
- python降序排列说true不存在_Python数据类型串讲(中)
- 关于量子计算机论文,终于,科学家们找到了只有量子计算机才能解决的问题
- 笔记-项目范围管理-确认范围与控制范围的区别
- 群辉NAS+KODI (二)----NAS文件配置+电视安装kodi安装配置
- Fabricjs在Canvas上插入照片并设置缩小和翻转属性
- Leaflet中使用awesome-markers插件显示带图标的marker
- CentOS7中多台服务器配置时钟同步