【Java并发编程】java并发框架Executor学习笔记
Java SE5的java.util.concurrent包中的执行器(Executor)将为你管理Thread对象,从而简化了并发编程。Executor在客户端和执行任务之间提供了一个间接层,Executor代替客户端执行任务。Executor允许你管理异步任务的执行,而无须显式地管理线程的生命周期。Executor在Java SE5/6中时启动任务的优选方法。Executor引入了一些功能类来管理和使用线程Thread,其中包括线程池,Executor,Executors,ExecutorService,CompletionService,Future,Callable等。
创建线程池
Executors类,提供了一系列工厂方法用于创先线程池,返回的线程池都实现了ExecutorService接口。
public static ExecutorService newFixedThreadPool(int nThreads)
创建固定数目线程的线程池。
public static ExecutorService newCachedThreadPool()
创建一个可缓存的线程池,调用execute 将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。
public static ExecutorService newSingleThreadExecutor()
创建一个单线程化的Executor。
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)
创建一个支持定时及周期性的任务执行的线程池,多数情况下可用来替代Timer类。
见类图,接口Executor只有一个方法execute,接口ExecutorService扩展了Executor并添加了一些生命周期管理的方法,如shutdown、submit等。一个Executor的生命周期有三种状态,运行 ,关闭 ,终止。
Callable,Future用于返回结果
Future代表一个异步执行的操作,通过get()方法可以获得操作的结果,如果异步操作还没有完成,则,get()会使当前线程阻塞。FutureTask实现了Future和Runable。Callable代表一个有返回值得操作。
实例:并行计算求和:
public class ConcurrentSum { private int coreCpuNum; private ExecutorService executor; private List<FutureTask<Long>> tasks = new ArrayList<FutureTask<Long>>(); public ConcurrentSum(){ coreCpuNum = Runtime.getRuntime().availableProcessors(); executor = Executors.newFixedThreadPool(coreCpuNum); } class SumCalculator implements Callable<Long>{ int nums[]; int start; int end; public SumCalculator(final int nums[],int start,int end){ this.nums = nums; this.start = start; this.end = end; } @Override public Long call() throws Exception { long sum =0; for(int i=start;i<end;i++){ sum += nums[i]; } return sum; } } public long sum(int[] nums){ int start,end,increment; // 根据CPU核心个数拆分任务,创建FutureTask并提交到Executor for(int i=0;i<coreCpuNum;i++){ increment = nums.length / coreCpuNum+1; start = i*increment; end = start+increment; if(end > nums.length){ end = nums.length; } SumCalculator calculator = new SumCalculator(nums, start, end); FutureTask<Long> task = new FutureTask<Long>(calculator); tasks.add(task); if(!executor.isShutdown()){ executor.submit(task); } } return getPartSum(); } public long getPartSum(){ long sum = 0; for(int i=0;i<tasks.size();i++){ try { sum += tasks.get(i).get(); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } return sum; } public void close(){ executor.shutdown(); } public static void main(String[] args) { int arr[] = new int[]{1, 22, 33, 4, 52, 61, 7, 48, 10, 11 }; long sum = new ConcurrentSum().sum(arr); System.out.println("sum: " + sum); } }
CompletionService
在上述例子中,getResult()方法的实现过程中,迭代了FutureTask的数组,如果任务还没有完成则当前线程会阻塞,如果我们希望任意任务完成后就把其结果加到result中,而不用依次等待每个任务完成,可以使用CompletionService。
它与ExecutorService最主要的区别在于submit的task不一定是按照加入时的顺序完成的。CompletionService对ExecutorService进行了包装,内部维护一个保存Future对象的BlockingQueue。只有当这个Future对象状态是结束的时候,才会加入到这个Queue中,take()方法其实就是Producer-Consumer中的Consumer。它会从Queue中取出Future对象,如果Queue是空的,就会阻塞在那里,直到有完成的Future对象加入到Queue中。所以,先完成的必定先被取出。这样就减少了不必要的等待时间。
实例:并行计算求和
public class ConcurrentSum2 { private int coreCpuNum; private ExecutorService executor; private CompletionService<Long> completionService; public ConcurrentSum2(){ //..... } class SumCalculator implements Callable<Long>{ //..... } public long sum(int[] nums){ int start,end,increment; // 根据CPU核心个数拆分任务,创建FutureTask并提交到Executor for(int i=0;i<coreCpuNum;i++){ increment = nums.length / coreCpuNum+1; start = i*increment; end = start+increment; if(end > nums.length){ end = nums.length; } SumCalculator task = new SumCalculator(nums, start, end); if(!executor.isShutdown()){ completionService.submit(task); } } return getPartSum(); } public long getPartSum(){ long sum = 0; for(int i=0;i<coreCpuNum;i++){ try { sum += completionService.take().get(); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } return sum; } public void close(){ executor.shutdown(); } }
【Java并发编程】java并发框架Executor学习笔记相关推荐
- 学习笔记:Java 并发编程⑥_并发工具_JUC
若文章内容或图片失效,请留言反馈. 部分素材来自网络,若不小心影响到您的利益,请联系博主删除. 视频链接:https://www.bilibili.com/video/av81461839 配套资料: ...
- 【Java并发编程】并发编程大合集
转载请注明出处:http://blog.csdn.net/ns_code/article/details/17539599 为了方便各位网友学习以及方便自己复习之用,将Java并发编程系列内容系列内容 ...
- 《Java并发编程实践-第一部分》-读书笔记
大家好,我是烤鸭: <Java并发编程实战-第一部分>-读书笔记. 第一章:介绍 1.1 并发历史: 多个程序在各自的进程中执行,由系统分配资源,如:内存.文件句柄.安全证书.进程间通信方 ...
- Java并发编程:并发容器之CopyOnWriteArrayList(转载)
Java并发编程:并发容器之CopyOnWriteArrayList(转载) 原文链接: http://ifeve.com/java-copy-on-write/ Copy-On-Write简称COW ...
- 【转】Java并发编程:并发容器之ConcurrentHashMap
JDK5中添加了新的concurrent包,相对同步容器而言,并发容器通过一些机制改进了并发性能.因为同步容器将所有对容器状态的访问都串行化了,这样保证了线程的安全性,所以这种方法的代价就是严重降低了 ...
- 并发编程——JUC并发编程知识脑图
摘要 并发编程在软件编程中尤为突出和重要,在当今面试或工作中也是不可缺少的.作为一名高级java开发工程师,并发编程的技能已经成为了重要的一项.本博文将详细介绍并发编程中的知识点和知识脑图,帮助大家更 ...
- 【檀越剑指大厂--并发编程】并发编程总结
并发编程 一.并发基础 1.什么是并行和并发? 并行,表示两个线程同时(同一时间)做事情. 并发,表示一会做这个事情,一会做另一个事情,存在着调度. 单核 CPU 不可能存在并行(微观上). 2.什么 ...
- 《Java Web开发入门很简单》学习笔记
<Java Web开发入门很简单>学习笔记 1123 第1章 了解Java Web开发领域 Java Web主要涉及技术包括:HTML.JavaScript.CSS.JSP.Servlet ...
- Java中如何创建自定义的注解学习笔记(MD版)
概要 Java中如何创建自定义的注解学习笔记(MD版). 博客 博客地址:IT老兵驿站. 前言 记得这篇笔记还是在泉州的龙玲酒店记录的,是一个周六的晚上,坐飞机从上海到泉州,从笔记中能勾起一些旅游的回 ...
最新文章
- MVC 多级目录菜单
- 成员函数 静态变量做默认参数_Scala系列 (二)Scala的独有特性提高开发效率学会之后玩转函数式与OOP!!...
- 不同坐标系下角速度_坐标系统及常见坐标系
- PAT L1-048 矩阵A乘以B
- Netty常见面试题 与 答案
- 《程序员代码面试指南》第二章 链表问题 反转部分单向链表
- linux系统账户口令管理
- python爬虫06
- PyCharm——如果不小心修改了第三方库文件,怎么办?
- 伺服系统 计算机仿真,减摇鳍电伺服系统的计算机仿真研究-应用科技-哈尔滨工程大学.PDF...
- html怎么设置字体的透明度,CSS字体透明度怎么设置?
- 一个好用的PLC调试神器
- E-R图转化为关系模型
- Robust regression(稳健回归)
- 电脑端播放m3u8视频
- iPhone6 微信视频通话没有声音
- 跳动爱心代码-李峋同款爱心代码(升级版)
- java编程找出吸血鬼数字,Java 找到四位数的所有吸血鬼数字 基础代码实例
- 在centos8环境下用asterisk18配置pjsip和webrtc音视频通话教程(一)
- Delphi中使用TThread类实现多线程
热门文章
- linux内核的反复--一切都是过程
- 验证redis的主从复制
- android 再按一次退出程序
- 直接启动SDK Manager: $ADNROID_HOME/tools/android
- Linux中默认的JDK版本设置
- latex的资料ftp
- Python中生成一个指定长度的随机字符串实现示例
- (二)SpringBoot 整合 JPA
- Preference跳转activity出错Unable to find explicit activity class
- Minty Fresh : So You Want To Write An Orchestration?