Java并发编程实践(读书笔记) 任务执行(未完)
来源:互联网 发布:excel分析股票数据 编辑:程序博客网 时间:2024/06/11 17:05
任务的定义
大多数并发程序都是围绕任务进行管理的.任务就是抽象和离散的工作单元.
任务的执行策略
1.顺序的执行任务
这种策略的特点是一般只有按顺序处理到来的任务.一次只能处理一个任务,后来其它任务都要等待处理.响应性很糟糕,吞吐量低.系统资源利用率低.
2.显示的为任务创建线程
为每个任务创建对应一个线程,响应快,系统资源利用路高.缺点是资源消耗量大,如果有大量任务要执行的话,系统迟早会因为无限制创建过多的线程而造成内存耗尽.特别当创建的线程数量远远大于系统的CPU核数,由于每一个核同一时刻只能执行一个线程,所以系统要执行很多不必要的线程上下文切换,造成资源大量浪费.
3.Executor框架
Executor接口本身很简单,就一个execute方法.但是由Executor这个接口衍生出来的类,功能非常强大.可以这么认为,Executor框架这是线程管理的工具.可以对线程的生命周期和执行策略进行管理.
Executor接口
public interface Executor { void execute(Runnable command);}
Executor框架是靠ThreadPoolExecutor实现的,简单理解为是一个线程池.其实是通过线程池和一个阻塞队列BlockingQueue<Runnable>对线程进行管理.
页面渲染器实例
该实例要实现2个任务,第一是渲染文本(速度快),第二个是渲染图片(速度慢).渲染图片的时候要先下载图片才能渲染.
1.第一种方式:顺序执行页面渲染
public class SingleThreadRenderer { public void renderPage(CharSequence source) { renderText(source);// 处理文本,速度快 List<ImageData> imageData = new ArrayList<>(); for (ImageInfo info : scanForImageInfo(source)) { imageData.add(info.downloadImage());// 下载图片,速度慢 } for (ImageData data : imageData) { renderImage(data);// 处理图片 } }}
这种实现方式简单,但是缺点也很明显,就是渲染文本和渲染图片不能并发执行,CPU利用率低.
2.第二种方式:使用Future实现页面渲染器
Future可以持有异步并发线程的执行结果,Executors可以对线程执行并发操作.
public class FutureRenderer { private final ExecutorService exec = Executors.newFixedThreadPool(Runtime .getRuntime().availableProcessors()); public void renderPage(CharSequence source) { final List<ImageInfo> imageInfos = scanForImageInfo(source); Callable<List<ImageData>> task = new Callable<List<ImageData>>() { public List<ImageData> call() throws Exception { List<ImageData> imageData = new ArrayList<>(); for (ImageInfo info : imageInfos) { imageData.add(info.downloadImage());// 下载图片,速度慢 } return imageData; } }; Future<List<ImageData>> f = exec.submit(task); //渲染图片的线程正在执行的同时处理文本任务 renderText(source);// 处理文本,速度快 try { List<ImageData> imageDatas = f.get(); for (ImageData data : imageDatas) { renderImage(data);// 处理图片 } } catch (InterruptedException | ExecutionException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
}
这种执行策略仍旧有局限性,这是由于并行运行异类任务并不会获得好的性能.只有大量相互独立的且同类的任务进行并发处理,才能获得真正性能提升.
3.第三种方式:使用CompletionService的页面渲染器
public class CompletionServiceRenderer { private final ExecutorService exec = Executors.newFixedThreadPool(Runtime .getRuntime().availableProcessors()); public void renderPage(CharSequence source) { final List<ImageInfo> imageInfos = scanForImageInfo(source); CompletionService<ImageData> completionService = new ExecutorCompletionService<>( exec); for (final ImageInfo info : imageInfos) { Callable<ImageData> task = new Callable<ImageData>() { public ImageData call() throws Exception { return info.downloadImage(); } }; completionService.submit(task); } renderText(source);// 处理文本,速度快 for (int i = 0; i < imageInfos.size(); i++) { try { Future<ImageData> future = completionService.take(); ImageData imageData = future.get(); renderImage(imageData);// 处理图片 } catch (InterruptedException | ExecutionException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }}
这种方式不用等下载所有图片才处理,而是每下载一张图片就处理,实现了很好的并发行.
- Java并发编程实践(读书笔记) 任务执行(未完)
- java并发编程实践_06任务执行
- 《Java并发编程实战》第六章 任务执行 读书笔记
- java并发编程实践学习(6 )任务执行
- JAVA并发编程实践--读书笔记
- Java并发编程实践 读书笔记
- Java并发编程实践读书笔记
- [Java 并发] Java并发编程实践 思维导图 - 第六章 任务执行
- 任务的取消与关闭(java并发编程实践读书笔记六)
- Java并发编程实践读书笔记(一)
- Java并发编程实践读书笔记(二)
- Java并发编程实践读书笔记(三)
- <Java 并发编程实践>读书笔记 --- 内部锁
- <Java 并发编程实践>读书笔记 --- 重排序
- <Java 并发编程实践>读书笔记 --- 线程封闭
- 《JAVA并发编程实践》读书笔记(一)
- 《JAVA并发编程实践》读书笔记(二)
- 《JAVA并发编程实践》读书笔记(三)
- QT使用sizeHint()遇到的问题
- 黑马程序员——集合框架总结
- EassyMock实践 捕获参数
- Tree
- cocos2d-x中的精灵
- Java并发编程实践(读书笔记) 任务执行(未完)
- android进程间通信(远程服务aidl,服务端)
- “三位一体”新颖教学方式,助你学得更快更好
- Java多线程并发编程之显示锁ReentrantLock和读写锁
- c++基数排序
- cocos2d-x中精灵的属性
- STM32的LCD
- Qt Permission denied问题
- Java多线程并发编程之构建自定义同步工具