Обновлять
Я обновил этот вопрос, чтобы включить исходный код реализации Java с использованием предложенного класса SwingWorker, чтобы получить тот же результат, что и в примере с Objective-C. Надеюсь, это поможет будущим искателям приключений.
Document myDoc = ...;
Model myModel = ...;
SwingWorker analyzeDocument = new SwingWorker<Dictionary, Void>() {
@Override
public Dictionary doInBackground() {
return myDoc.analyze();
}
@Override
public void done() {
try {
stats = get();
myModel.setDict(stats);
myModel.setNeedsDisplay(true);
} catch(InterruptedException ex) {
// log
} catch(ExecutionException ex) {
// log
}
}
};
analyzeDocument.execute();
Исходное сообщение
Я неопытен, когда дело доходит до параллельного программирования, и я надеялся, что кто-то сможет объяснить мне, как я могу этого добиться.
В Objective-C (с GCD) вы можете сделать что-то вроде этого:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, NULL), ^{
NSDictionary *stats = [myDoc analyze];
dispatch_async(dispatch_get_main_queue(), ^{
[myModel setDict:stats];
[myStatsView setNeedsDisplay:YES];
[stats release];
});
});
Этот код выполнит [myDoc analyze]
в фоновом потоке после функции обратного вызова для обновления пользовательского интерфейса, который будет выполняться в основном потоке. Другими словами, фоновый поток посылает прерывание основному потоку, добавляя анонимную функцию в очередь основного потока для вызова. Очевидно, что я не смогу использовать анонимные функции в Java, но это не относится к делу.
Я заинтересован в том, чтобы сделать что-то в этом отношении на Java. У меня есть объект Runnable
, который выполняет кучу операций в файловой системе. Когда он закончится, я хочу соответствующим образом обновить пользовательский интерфейс.
Чтобы при этом не зависал основной поток (например, backgroundThread.join();
), я настроил фоновый поток на выполнение функции обратного вызова для обновления пользовательского интерфейса. Но это не очень хорошая идея, я не хочу, чтобы поток, не относящийся к графическому интерфейсу, обновлял графический интерфейс.
Некоторые другие идеи, о которых я думал, - это опрос, но это похоже на выбрасывание циклов в окно. По тому же мнению, использование фьючерсов также не является ответом. Все это, кажется, противоречит цели асинхронного действия.
Единственное, что я могу придумать, это использовать SwingUtilities.invokeLater
из фонового потока и использовать его для обновления графического интерфейса. Но мне любопытно, в каком потоке это будет выполнено.
Может быть, мое восприятие просто искажено, но кажется, что было бы довольно большой частью этого не воспользоваться. Я просто пытаюсь сделать это неправильно?