我正在制作新闻更新应用。为此,它需要能够在给定的时间段内获得更新。在这里我已经创建了一个计时器来在给定的时间段内运行可调用插件。在这里,我使用了FixedThreadPool(执行器)。 为此,我想要知道未来何时完成其工作,以便我可以调用updateHeadlines方法。但是当我使用finished.get()时它阻止了gui。是否有一种方法可以在作业完成后无阻塞地知道我可以在此之后更新GUI。
for (Callable curplugin : plugin) {
new Timer(((NewsPlugin) curplugin).getUpdateFrequency(), new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
Future<?> finished = executor.submit(curplugin);
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
try {
ArrayList<Headline> news = (ArrayList) finished.get();
updateHeadlines();
} catch (InterruptedException ex) {
Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
} catch (ExecutionException ex) {
Logger.getLogger(MainFrame.class.getName()).log(Level.SEVERE, null, ex);
}
}
});
}
}).start();
}
&#13;
答案 0 :(得分:2)
如果您使用的是Java 8.有一个完整的未来,您可以在其中注册一个回调,当任务完成时将调用该回调。我认为这会对你有所帮助。
这可能会对您有所帮助Callback with CompletableFuture
答案 1 :(得分:2)
不需要合并Timer
和ExecutorService
,也不需要使用回调。相反,安排调用插件的Runnable
,并安排invokeLater
显示结果:
for (NewsPlugin plugin : plugins) {
Runnable task = () -> {
List<Headline> news;
try {
news = plugin.call(); /* There's really no need for plugin to be `Callable` */
} catch (Exception ex) {
ex.printStackTrace();
}
java.awt.EventQueue.invokeLater(this::updateHeadlines);
};
int period = plugin.getUpdateFrequency();
executor.scheduleAtFixedRate(task, period, period, TimeUnit.MILLISECONDS);
}
答案 2 :(得分:0)
从Java 8开始,您可以使用CompletableFuture
在完成一次性任务时获得回调。在Java 8之前,您可以使用Guava的ListenableFuture
,它具有类似的功能。
对于循环任务,使用observable模式,该模式是处理从重复任务返回的多个项目的未来对应模式。 Java虽然似乎没有提供良好的OOTB解决方案。