SwingWorker
を使用し、publishメソッドを利用して、更新をEDTに公開することをお勧めします。EDTは、次にスケジュールされたときに1つ以上の更新を適用します。たとえば、計算結果がInteger
インスタンスであるとします。
// Boolean flag to determine whether background thread should continue to run.
AtomicBoolean running = new AtomicBoolean(true);
new SwingWorker<Void, Integer>() {
public Void doInBackground() {
while (running.get()) {
// Do calculation
Integer result = doCalculation();
publish(result);
}
}
protected void process(List<Integer> chunks) {
// Update UI on EDT with integer results.
}
}
別のアプローチは、スケジュールされるたびに結果Runnable
を単純に消費する単一のインスタンスを作成することです。Queue
これは、内部で動作する方法と似ていますが、実装を制御し、プールされたスレッドの1つを永続的に保持することを回避SwingWorker
できるという点で、わずかに制御が強化されます。Queue
SwingWorker
private final Queue<Integer> resultQueue = Collections.synchronizedList(new LinkedList<Integer>());
// Thread-safe queue to hold results.
// Our re-usable Runnable to be run on the EDT. Consumes all results from the result queue
// before releasing the lock, although could obviously change this to consume up to N results.
Runnable consumer = new Runnable() {
public void run() {
synchronized(resultQueue) {
Integer result;
while ((result = resultQueue.take()) != null) {
// Update UI.
}
}
}
}
...
// Business logic to run on background thread. Conditionally schedules the EDT to run as required.
while (true) {
Integer result = doCalculation();
synchronized(resultQueue) {
boolean scheduleEdt = resultQueue.isEmpty();
// Queue was empty before this result is added so need to schedule the EDT to run again.
resultQueue.add(result);
}
if (scheduleEdt) {
SwingUtilities.invokeLater(consumer);
} else {
System.err.println("EDT already scheduled -> Avoiding unecessary reschedule.");
}
}