from: https://www.cnblogs.com/shipengzhi/articles/2067154.html

import java.util.concurrent.*;
public class ConcurrentCalculator2 { //from: https://www.cnblogs.com/shipengzhi/articles/2067154.html
private ExecutorService executorService;
private CompletionService<Long> completionService;
private int cpuCoreNumber; public ConcurrentCalculator2() {
cpuCoreNumber = Runtime.getRuntime().availableProcessors();
executorService = Executors.newFixedThreadPool(cpuCoreNumber);
completionService = new ExecutorCompletionService<Long>(executorService);
} public Long sum(final int[] numbers) {
for (int i = 0; i < cpuCoreNumber; i++) { //(页数)根据CPU核心个数拆分任务,创建FutureTask并提交到Executor
int increment = numbers.length / cpuCoreNumber + 1; //(每页多少条)
int start = increment * i; //首条数据-->当前页 的
int end = increment * i + increment; //首条数据-->(当前页+1)的
if (end > numbers.length)
end = numbers.length;
SumCalculator subCalc = new SumCalculator(numbers, start, end, (i+1));
if (!executorService.isShutdown()) {
completionService.submit(subCalc);
}
}
System.out.println("所有计算任务提交完毕, 主线程接着干其他事情!");
return getResult();
} public Long getResult() { //迭代每个只任务,获得部分和,相加返回
Long result = 0l;
int index =0;
System.out.println("-->2-"+ Thread.currentThread().getName()+"线程 List<Future<Long>>集合中的第一个元素开始遍历之前【就开始 全部执行掉MyCallable构造方法(不一定按集合内部顺序)!】");
for (int i = 0; i < cpuCoreNumber; i++) {
try {
index++;
Long subSum = completionService.take().get();
System.out.println("-->4-"+Thread.currentThread().getName()+"线程 "+"-List<Future<Long>>集合遍历ing(一定按集合内部顺序)【有时候3和4会<成对>交叉执行】-- 打印第:"+index+"页累计的和:" + subSum);
result += subSum;
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
System.out.println("-->5-总结-->线程的实现方法总是先一步于List<Future<Long>>的遍历(线程的impl分页计算各页的总和,List<Future>负责把所有页的和累加!");
return result; } public void close() {
executorService.shutdown();
} class SumCalculator implements Callable<Long> {//Runnable
private int[] numbers;
private int start;
private int end;
private int index; public SumCalculator(final int[] numbers, int start, int end, int index) {
this.numbers = numbers;
this.start = start;
this.end = end;
this.index = index;
System.out.println("-->1-"+Thread.currentThread().getName() +"线程-生成子线程计算任务(调用构造函数)第 "+ index +"次");
} @Override
public Long call() throws Exception {
Long sum = 0l;
for (int i = start; i < end; i++) {
sum += numbers[i];
}
//子线程-->休眠5秒钟,观察主线程行为,预期的结果是主线程会继续执行,到要取得FutureTask的结果是等待直至完成。
Thread.sleep(3000); System.out.println("-->3-" + Thread.currentThread().getName() + "线程执行计算任务 打印current数据:" +"startIndex:"+ start + ";endIndex:" + end+ ";sum:" + "=" + sum);
return sum;
}
}
public static void main(String[] args) {
int[] numbers = new int[] { 0, 1, 2 };
ConcurrentCalculator2 calculator = new ConcurrentCalculator2();
Long sum = calculator.sum(numbers);
System.out.println("-->10-res:"+sum);
calculator.close();
} /** * Callable 和 Future接口 * Callable是类似于Runnable的接口,实现Callable接口的类和实现Runnable的类都是可被其它线程执行的任务。 * Callable和Runnable有几点不同: * (1)Callable规定的方法是call(),而Runnable规定的方法是run(). * (2)Callable的任务执行后可返回值,而Runnable的任务是不能返回值的。 * (3)call()方法可抛出异常,而run()方法是不能抛出异常的。 * (4)运行Callable任务可拿到一个Future对象, * Future 表示异步计算的结果。它提供了检查计算是否完成的方法,以等待计算的完成,并检索计算的结果。 * 通过Future对象可了解任务执行情况,可取消任务的执行,还可获取任务执行的结果。 */
}

java并发编程-Executor框架 + Callable + Future的更多相关文章

  1. Java 并发编程——Executor框架和线程池原理

    Eexecutor作为灵活且强大的异步执行框架,其支持多种不同类型的任务执行策略,提供了一种标准的方法将任务的提交过程和执行过程解耦开发,基于生产者-消费者模式,其提交任务的线程相当于生产者,执行任务 ...

  2. (转)java并发编程--Executor框架

    本文转自https://www.cnblogs.com/MOBIN/p/5436482.html java并发编程--Executor框架 只要用到线程,就可以使用executor.,在开发中如果需要 ...

  3. Java 并发编程——Executor框架和线程池原理

    Java 并发编程系列文章 Java 并发基础——线程安全性 Java 并发编程——Callable+Future+FutureTask java 并发编程——Thread 源码重新学习 java并发 ...

  4. java并发编程-Executor框架

    Executor框架是指java 5中引入的一系列并发库中与executor相关的一些功能类,其中包括线程池,Executor,Executors,ExecutorService,Completion ...

  5. Java 并发编程 Executor 框架

    本文部分摘自<Java 并发编程的艺术> Excutor 框架 1. 两级调度模型 在 HotSpot VM 的线程模型中,Java 线程被一对一映射为本地操作系统线程.在上层,Java ...

  6. Java并发编程:ThreadPoolExecutor + Callable + Future(FutureTask) 探知线程的执行状况

    如题 (总结要点) 使用ThreadPoolExecutor来创建线程,使用Callable + Future 来执行并探知线程执行情况: V get (long timeout, TimeUnit ...

  7. Java并发编程-Executor框架(转)

    本文转自http://blog.csdn.net/chenchaofuck1/article/details/51606224 感谢作者 我们在传统多线程编程创建线程时,常常是创建一些Runnable ...

  8. java并发编程--Executor框架(一)

    摘要:        Eexecutor作为灵活且强大的异步执行框架,其支持多种不同类型的任务执行策略,提供了一种标准的方法将任务的提交过程和执行过程解耦开发,基于生产者-消费者模式,其提交任务的线程 ...

  9. Java并发编程-Executor框架集

    Executor框架集对线程调度进行了封装,将任务提交和任务执行解耦. 它提供了线程生命周期调度的所有方法,大大简化了线程调度和同步的门槛. Executor框架集的核心类图如下: 从上往下,可以很清 ...

随机推荐

  1. C#怎样用文件读写在文件的原有基础上追加一行数据

    首先添加命名空间using System.IO;这里有两种方法,希望对你有帮助,操作文件时,一定要记得及时关闭流. 第一种方法: string path="D\1.txt";//文 ...

  2. mount ntfs-3g , fstab里的配置没有效果

    把ntfs-3g配置在 fstab 里,mount 时会报 No such device 网上也有在嵌入式系统里发生的类似例子. 没有解决方法,也不准备再研究了. 准备在机器启动之后,手动下面的命令 ...

  3. mysql导出导入数据库表

    1.下载数据库 mysqldump db_name  -h 192.168.5.162 -uroot -p > /var/www/db_name.sql(这个可以自定义) 2,下载数据库中的某个 ...

  4. Oracle11g温习-第九章:表空间和数据文件管理

    2013年4月27日 星期六 10:37 1.tablespace 功能:从逻辑上简化数据库的管理 2.tablespace 概述 一个database 对应多个tablespace ,一个table ...

  5. WinForm窗体自适应分辨率

    我们自己编写程序的界面,会遇到各种屏幕分辨率,只有自适应才能显的美观.实际上,做到这点也很简单,就是首先记录窗体和它上面控件的初始位置和大小,当窗体改变比例时,其控件的位置和大小也按此比例变化即可.因 ...

  6. 在Windows下配置svn服务端钩子程序(部分)

    需求一,svn提交时必须填写log日志的需求,如何进行配置呢?请看下面. 需要在版本库目录下找到hooks文件夹,我的版本库是dxoffice,所以是这个目录,你要找自己的目录 然后进入,创建一个pr ...

  7. maven分别打包开发、生产配置文件

    项目工程针对开发和生产有两套配置,开发配置文件目录:src/main/resources/    applicationContext.xml (开发和生产共用)    dubbo.propertie ...

  8. vue input框数字后保留两位小数正则

    <el-input type="text" v-model.trim="ruleForm2.marketPrice" maxlength="10 ...

  9. webservice-jdk客户端代码

    使用wsimport.exe 生成客户端代码 使用JDK的bin文件夹中,有一个wsimport.exe,这个工具依据wsdl文件生成相应的类文件,然后用这些文件就可以像调用本地类一样调用本地的类一样 ...

  10. HDU 4091 Zombie’s Treasure Chest 分析 难度:1

    Zombie’s Treasure Chest Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/ ...