1 package charactermanaj.graphics;
\r
3 import java.util.logging.Level;
\r
4 import java.util.logging.Logger;
\r
8 * 各パーツ情報をもとに非同期にイメージを合成する
\r
11 public class AsyncImageBuilder extends ImageBuilder implements Runnable {
\r
16 private static final Logger logger = Logger.getLogger(AsyncImageBuilder.class.getName());
\r
19 * 非同期にイメージを構築するためのジョブ定義.<br>
\r
20 * リクエストを受け付けたことを示すイベントおよび、リクエストが放棄されたことを示すイベントを受け取ることができる.<br>
\r
24 public interface AsyncImageBuildJob extends ImageBuildJob {
\r
26 * リクエストを受け付けた場合に呼び出される.<br>
\r
27 * @param ticket このイメージビルダでリクエストを受け付けた通し番号
\r
29 void onQueueing(long ticket);
\r
32 * リクエストを処理するまえに破棄された場合に呼び出される.<br>
\r
40 private final Object lock = new Object();
\r
43 * チケットのシリアルナンバー.<br>
\r
44 * リクエストがあるごとにインクリメントされる.<br>
\r
46 private long ticketSerialNum = 0;
\r
49 * リクエストされているジョブ、なければnull
\r
51 private ImageBuildJob requestJob;
\r
56 private volatile boolean stopFlag;
\r
61 private Thread thread;
\r
65 * @param imageLoader イメージローダー
\r
67 public AsyncImageBuilder(ColorConvertedImageCachedLoader imageLoader) {
\r
69 thread = new Thread(this);
\r
70 thread.setDaemon(true);
\r
77 logger.log(Level.FINE, "AsyncImageBuilder thread started.");
\r
79 // 停止フラグがたてられるまで繰り返す.
\r
83 synchronized (lock) {
\r
84 while (!stopFlag && requestJob == null) {
\r
98 AsyncImageBuilder.super.requestJob(job);
\r
100 } catch (InterruptedException ex) {
\r
101 logger.log(Level.FINE, "AsyncImageBuilder thead interrupted.");
\r
102 // 割り込みされた場合、単にループを再開する.
\r
104 } catch (Exception ex) {
\r
105 logger.log(Level.SEVERE, "AsyncImageBuilder failed.", ex);
\r
106 // ジョブ合成中の予期せぬ例外はログに記録するのみで
\r
107 // スレッドそのものは停止させない.
\r
108 // (Error系は、たぶんアプリ自身が続行不能な障害なので停止する.)
\r
111 logger.log(Level.FINE, "AsyncImageBuilder thread stopped.");
\r
115 * イメージ作成ジョブをリクエストする.<br>
\r
116 * イメージ作成ジョブは非同期に実行される.<br>
\r
117 * 処理がはじまる前に新しいリクエストで上書きされた場合、前のリクエストは単に捨てられる.<br>
\r
120 public boolean requestJob(ImageBuildJob imageSource) {
\r
121 synchronized (lock) {
\r
122 // 現在処理待ちのリクエストがあれば、新しいリクエストで上書きする.
\r
123 if (this.requestJob != null && this.requestJob instanceof AsyncImageBuildJob) {
\r
124 ((AsyncImageBuildJob) this.requestJob).onAbandoned();
\r
127 // リクエストをセットして待機中のスレッドに通知を出す.
\r
128 this.requestJob = imageSource;
\r
129 if (imageSource != null && imageSource instanceof AsyncImageBuildJob) {
\r
130 ((AsyncImageBuildJob) imageSource).onQueueing(++ticketSerialNum);
\r
140 * @return 生きていればtrue
\r
142 public boolean isAlive() {
\r
143 return thread.isAlive();
\r
149 public void start() {
\r
150 if (!thread.isAlive()) {
\r
159 public void stop() {
\r
160 if (thread.isAlive()) {
\r
162 thread.interrupt();
\r
166 } catch (InterruptedException ex) {
\r