任務執行(二)
阿新 • • 發佈:2019-02-05
一、序列的頁面渲染器
二、為了使頁面渲染器實現更高的併發性,首先將渲染過程分解為兩個任務,一個是渲染所有的文字,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);//如果任務正在執行,將被中斷
}
}