最初に ProgressMonitor を定義します。
progressMonitor = new ProgressMonitor(parent, "Starting processing ...", "", 0, maxNumberProcesses+1);
progressMonitor.setProgress(0);
同じスレッドで ExecutorService と invokeAll() を使用して Callable のリストを処理します。
ExecutorService execService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); // use all available processors at startup
execService.invokeAll(callables); // wait for all tasks to complete
execService.shutdownNow(); // free thread pool resources
各 Callable の形式は次のとおりです。
class Callable implements Callable<List<String>>
{
public List<String> call()
{
List<String> files = doSomeStuff();
progressBarUpdate();
return files;
}
}
すなわち; 各 Callable は、progressBarUpdate() を呼び出します。
private void progressBarUpdate()
{
if (progressMonitor != null)
{
Lock lock = new ReentrantLock();
lock.lock();
try
{
progressMonitor.increment();
}
finally
{
lock.unlock(); // release lock
}
}
}
各 doSomeStuff() には独自の例外処理があり、エラーが発生するか例外がスローされると、null 値が返されます。これが、戻り値の型がリストであり、そのような場合は null を返す理由です。Callable とそれらが返すファイルのリストの間にクロスオーバーはありません。それらはすべて独自のファイルのリストを維持します。
正常に動作することがわかりましたが、次の形式の InterruptedException がスローされることがあります。
Disposal was interrupted:
java.lang.InterruptedException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:503)
at java.awt.EventQueue.invokeAndWait(EventQueue.java:1263)
at java.awt.Window.doDispose(Window.java:1209)
at java.awt.Dialog.doDispose(Dialog.java:1196)
at java.awt.Window.dispose(Window.java:1147)
at javax.swing.ProgressMonitor.close(ProgressMonitor.java:311)
at javax.swing.ProgressMonitor.setProgress(ProgressMonitor.java:264)
モニターの最大値に達したときに setProgress() が close() を呼び出すことを示しています。
public void setProgress(int nv) {
if (nv >= max) {
close();
}
...
そして close() には、他のスレッドセーフでない呼び出しが多数含まれています。
条件 nv>=max が満たされないようにコードを変更し、invokeAll() の後に明示的に ProgressMonitor.close() を呼び出しましたが、そのようなアプローチが完全にスレッドセーフであるとはまだ確信していません。
他の誰かがこの状況に遭遇し、堅実な解決策を見つけましたか?
ありがとう
グラハム
PS。ProgressMonitor は Swing ウィジェットではありませんが、Swing コンポーネントをカプセル化することに注意してください。その結果、ProgressMonitor が EDT で実行されないようにしました。