java并发编程实践 读书笔记_Java并发编程实践(读书笔记) 任务执行(未完)

任务的定义

大多数并发程序都是围绕任务进行管理的.任务就是抽象和离散的工作单元.

任务的执行策略

1.顺序的执行任务

这种策略的特点是一般只有按顺序处理到来的任务.一次只能处理一个任务,后来其它任务都要等待处理.响应性很糟糕,吞吐量低.系统资源利用率低.

2.显示的为任务创建线程

为每个任务创建对应一个线程,响应快,系统资源利用路高.缺点是资源消耗量大,如果有大量任务要执行的话,系统迟早会因为无限制创建过多的线程而造成内存耗尽.特别当创建的线程数量远远大于系统的CPU核数,由于每一个核同一时刻只能执行一个线程,所以系统要执行很多不必要的线程上下文切换,造成资源大量浪费.

3.Executor框架

Executor接口本身很简单,就一个execute方法.但是由Executor这个接口衍生出来的类,功能非常强大.可以这么认为,Executor框架这是线程管理的工具.可以对线程的生命周期和执行策略进行管理.

Executor接口

public interfaceExecutor {voidexecute(Runnable command);

}

Executor框架是靠ThreadPoolExecutor实现的,简单理解为是一个线程池.其实是通过线程池和一个阻塞队列BlockingQueue对线程进行管理.

页面渲染器实例

该实例要实现2个任务,第一是渲染文本(速度快),第二个是渲染图片(速度慢).渲染图片的时候要先下载图片才能渲染.

1.第一种方式:顺序执行页面渲染

public classSingleThreadRenderer {public voidrenderPage(CharSequence source) {

renderText(source);//处理文本,速度快

List imageData = new ArrayList<>();for(ImageInfo info : scanForImageInfo(source)) {

imageData.add(info.downloadImage());//下载图片,速度慢

}for(ImageData data : imageData) {

renderImage(data);//处理图片

}

}

}

这种实现方式简单,但是缺点也很明显,就是渲染文本和渲染图片不能并发执行,CPU利用率低.

2.第二种方式:使用Future实现页面渲染器

Future可以持有异步并发线程的执行结果,Executors可以对线程执行并发操作.

public classFutureRenderer {private final ExecutorService exec =Executors.newFixedThreadPool(Runtime

.getRuntime().availableProcessors());public voidrenderPage(CharSequence source) {final List imageInfos =scanForImageInfo(source);

Callable> task = new Callable>() {public List call() throwsException {

List imageData = new ArrayList<>();for(ImageInfo info : imageInfos) {

imageData.add(info.downloadImage());//下载图片,速度慢

}returnimageData;

}

};

Future> f =exec.submit(task);//渲染图片的线程正在执行的同时处理文本任务

renderText(source);//处理文本,速度快

try{

List imageDatas =f.get();for(ImageData data : imageDatas) {

renderImage(data);//处理图片

}

}catch (InterruptedException |ExecutionException e) {//TODO Auto-generated catch block

e.printStackTrace();

}

}

}

这种执行策略仍旧有局限性,这是由于并行运行异类任务并不会获得好的性能.只有大量相互独立的且同类的任务进行并发处理,才能获得真正性能提升.

3.第三种方式:使用CompletionService的页面渲染器

public classCompletionServiceRenderer {private final ExecutorService exec =Executors.newFixedThreadPool(Runtime

.getRuntime().availableProcessors());public voidrenderPage(CharSequence source) {final List imageInfos =scanForImageInfo(source);

CompletionService completionService = new ExecutorCompletionService<>(

exec);for (finalImageInfo info : imageInfos) {

Callable task = new Callable() {public ImageData call() throwsException {returninfo.downloadImage();

}

};

completionService.submit(task);

}

renderText(source);//处理文本,速度快

for (int i = 0; i < imageInfos.size(); i++) {try{

Future future =completionService.take();

ImageData imageData=future.get();

renderImage(imageData);//处理图片

}catch (InterruptedException |ExecutionException e) {//TODO Auto-generated catch block

e.printStackTrace();

}

}

}

}

​这种方式不用等下载所有图片才处理,而是每下载一张图片就处理,实现了很好的并发行.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值