我的Swing应用程序有一个表,当从外部源获取一些数据时,该表被填充。要显示数据,我正在使用SwingWorker线程,该线程是从应该以这种方式获取数据的线程调用的:
// SwingWorker Thread
private class DisplayRowsTask extends SwingWorker<Void, Object[]> {
private Vector<String[]> _data;
@Override
protected Void doInBackground() {
while (_continue && !hasError()) {
// some logic to fetch and place data in _data
// data adjustment
for (String[] row : _data) publish (row);
_data = new Vector<String[]>();
}
return null;
}
@Override
protected void process(List<Object[]> rows) {
for (Object[] row : rows) ((DefaultTableModel)_table.getModel()).addRow(row);
}
}
显示的结果是正确的,除了CPU使用率为100%(并且结束!)之外,一切正常,特别是在频繁提取大量数据的情况下。我该如何限制这种用法?
另一个问题可能并不完全相关:如何知道数据是否已显示在表格中? “SwingWorker.isDone()”方法不提供此信息
答案 0 :(得分:1)
您的CPU自然而然地高达100%,因为您在while (!task.isDone());
中闲置 run()
。 SwingWorker
是通过调用execute();
异步执行的,因此您无需在Thread
中执行它。你不应该在Swing中使用Thread
。 SwingWorker
完成了这项工作。它有钩子方法,可以在代码完成时调用它。
如果要执行许多任务,请在SwingWorker
本身实现它们。
这样的事情:
@Override
protected Void doInBackground() {
while (_continue && !hasError()) {
// do some adjustments around _data
for (String[] row : _data) publish (row);
}
return null;
}
另一个问题:
我认为addRow(...)
会引发事件。您的表应该获取此事件并使组件无效。如果您想在SwingWorker
完成后执行代码,请覆盖done()
方法。
答案 1 :(得分:1)
不回答......
不知道您尝试了什么,因为我无法正确生成实现Essential Java的100%CPU使用率,如果您是IDE用户,那么您可以使用内置JProfiler
来分析代码,然后在那里你可以看到当前JVM中的所有重要事件,但基本上你有三个选择
1)实现Executor & SwingWorker,注意关于take error from Future
2)通过将方法包装到Runnable#Thread,通知GUI的输出必须包含在invokeLater
中,
3)创建一些ThreadFactory or implements Executor,在invokeLater
需要的某些情况下,GUI的通知输出必须包含invokeAndWait
4)您可以模拟/比较性能问题Christmas Tree Applications