一、串行的页面渲染器
class SingleThreadRenderer {
void renderPage(CharSequence source) {
renderText(source);
List<ImageData> imageData = new ArrayList<ImageData>();
for(ImageInfo imageInfo : scanForImageInfo(source)) {
imageData.add(imageInfo.downloadImage());
}
for(ImageData data : imageData) {
renderImage(data);
}
}
}
另一个是下载所有的图像。
Callable和Future有助于表示协同任务之间的交互。下面的代码中创建了一个Callable来下载所有的图像,
并将其提交到一个ExecutorService这将返回一个描述任务执行情况的Future。当主任务需要图像时,它会
等待Future.get的调用结果。如果幸运的话,当开始请求时所有的图像就已经下载完成了,即使没有,至少
图像的下载任务也已经提交开始了。
使用Future等待图像下载
class FutureRenderer {
private final ExecutorService executor = .;
void renderPage(CharSequence source) {
final List<ImageInfo> imageInfos = scanForImageInfo(source);
Callable<List<ImageData>> task = new Callable<List<ImageData>> () {
public List<ImageData> call() {
List<ImageData> result = new ArrayList<ImageData>();
for(ImageInfo imageInfo : imageInfos) {
result.add(imageInfo.downloadImage());
}
return result;
}
};
Future<List<ImageData>> future = executor.submit(task);
renderText(source);
try{
List<ImageData> imageData = future.get();
for(ImageData data : imageData) {
rederImage(data);
}
} catch (InterruptedException e) {
//重新设置线程的中断状态
Thread.currentThread().interrupt();
//由于不需要结束,因此取消任务
future.cancel(true);
} catch (ExecutionException e) {
throw launderThrowable(e.getCause());
}
}
}
三、使用CompletionService实现页面渲染器
可以通过CompletionService从两个方法来提高页面渲染器的性能:缩短总运行时间以及提高响应性。为每一幅
图像的下载都创建一个独立任务,并在线程池中执行它们,从而将串行的下载过程转换为并行的过程:这将减少
下载所有图像的总时间。此外,通过从CompletionService中获取结果以及使每张图片在下载完成后立刻显示出来,
能使用户获得一个更加动态和更高响应性的用户界面。
class Renderer {
private final ExecutorService executor;
Renderer(ExecutorService executor) {
this.executor = executor;
}
void renderPage(CharSequence source ) {
List<ImageInfo> info = scanForImageInfo(source);
CompletionService<ImageData> completionService = new ExecutorCompletionService<ImageData>(executor);
for(final ImageInfo imageInfo : info) {
completionService.submit(new Callable<ImageData>() {
public ImageData call() {
return imageInfo.downloadImage();
}
});
}
renderText(source);
try{
for(int t = 0, n = info.size(); t < n; t++) {
Future<ImageData> f = completionService.take();
ImageData imageData = f.get();
renderImage(imageData);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (ExecutionException e) {
throw launderThrowable(e.getCause());
}
}
}
通过Future来取消任务
public static void timedRun(Runnable r,long timeout,TimeUnit unit) throws InterruptedException {
Future<?> task = taskExec.submit(r);
try{
task.get(timeout, unit);
} catch(TimeoutException e) {
//接下来任务将被取消
} catch(ExecutionException e) {
throw launderThrowable(e.getCause());
} finally {
task.cancel(true);//如果任务正在运行,将被中断
}
}