我有一个 TableView,显示最后 N 个项目、顶部的新项目、从底部删除项目等...似乎发生的情况是 CPU 负载随着时间的推移而增加,导致同一台计算机上的其他 X 应用程序变得缓慢。
平台详细信息:Redhat 6.7,32 位,Java 1.8u40
我尝试过的事情
- 引入了 runLater() - 原始代码从非 FX 线程更新了可观察列表 - 显然这是错误的
- 优化 - 如果尚未进行更新,则仅在 JavaFX 应用程序线程上放置新的 Runnables
- 优化 - 批量更新可观察列表而不是单独添加
- 使用jvisual VM来识别任何内存泄漏,找不到任何东西。
- I've tried to recreate this
- Windows 7(在金属上)- JDK 8u40 64 位 => 不会发生
- Ubuntu 16.04 JDK 8u40 64 位(在具有 vmwgfx 的虚拟机内)=> 不会发生
- Ubuntu 16.04 OpenJDK + OpenJFX 最新版 (8u91)(在金属上)=>does occur
VisualVM - 犹太硬件上的 Redhat 6u7(32 位)
VisualVM - 旧硬件 (2008 iMac) 上的 Ubuntu 16.04(64 位)
这个问题是较大应用程序的一部分,但我将其隔离为下面的一个较小示例。这使得其他应用程序在几分钟后变得缓慢,但仅限于 Redhat 6u7 平台。
public class TableUpdater extends Application {
private int maxItems = 30;
private AtomicBoolean pending = new AtomicBoolean();
public class Thing {
private String foo;
public Thing(String foo) {
this.foo = foo;
}
public String getFoo() {
return foo;
}
@Override
public int hashCode() {
return foo.hashCode();
}
@Override
public boolean equals(Object obj) {
if (! (obj instanceof Thing)) {
return false;
}
return ((Thing)obj).foo.equals(foo);
}
}
public static void main(String[] args) {
launch(args);
}
private int counter = 0;
private ObservableList<Thing> data;
private List<Thing> itemsToAdd = Collections.synchronizedList(new ArrayList<Thing>());
@Override
public void start(Stage primaryStage) throws Exception {
TableView<Thing> table = new TableView<>();
data = FXCollections.observableArrayList();
table.setItems(data);
TableColumn<Thing, String> fooCol = new TableColumn<>("Foo");
fooCol.setCellValueFactory(new PropertyValueFactory<Thing, String>("foo"));
table.getColumns().addAll(fooCol);
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(() -> {
add(new Thing(String.format("%08d", counter++)));
}, 0, 2, TimeUnit.MILLISECONDS);
primaryStage.setScene(new Scene(table));
primaryStage.setWidth(400);
primaryStage.setHeight(400);
primaryStage.show();
}
private void add(Thing thing) {
itemsToAdd.add(thing);
if (!pending.getAndSet(true)) {
Platform.runLater(() -> {
synchronized (itemsToAdd) {
Collections.reverse(itemsToAdd);
data.addAll(0, itemsToAdd);
itemsToAdd.clear();
}
if (data.size() > maxItems) {
data.remove(maxItems, data.size());
}
pending.set(false);
});
}
}
}
问题
- 这个问题与我更新表的方式或潜在的错误有关吗?
- 还有更有效的方法来更新表吗?
尝试使用 G1GC 垃圾收集器。我有一个类似但不完全相同的问题(表视图中存在大量持久对象),该问题已通过使用 G1GC 解决。
java XX:+UseG1GC
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)