У меня есть TableView, который показывает последние N элементов, новые элементы вверху, удаляет элементы снизу и т.д. То, что, похоже, происходит, - это загрузка ЦП с течением времени, чтобы указать, где другие X-приложения на одном компьютере становятся вялыми.
Подробная информация о платформе: Redhat 6.7, 32 бит, Java 1.8u40
Вещи, которые я пробовал
- Введенный runLater() - исходный код обновил наблюдаемый список из потока non-FX - видимо, это неправильно
- Оптимизация - помещайте новые Runnables в поток приложений JavaFX, если еще не выполняется обновление.
- Оптимизировать -bulk обновления в списке наблюдаемых, а не отдельных добавляет
- использовал виртуальную виртуальную машину для определения утечек памяти, не смог найти ничего.
- Я пытался воссоздать это
- Windows 7 (по металлу) - JDK 8u40 64 бит = > не встречается
- Ubuntu 16.04 JDK 8u40 64 бит (внутри виртуальной машины с vmwgfx) = > не происходит
- Ubuntu 16.04 OpenJDK + OpenJFX последний (8u91) (по металлу) = > выполняет
JVisual VM - Redhat 6u7 (32 бит) на новом оборудовании
JVisual VM - Ubuntu 16.04 (64 бит) на старом оборудовании (2008 iMac)
Эта проблема была частью более крупного приложения, но я выделил ее как меньший пример ниже. Это делает другие приложения вялыми через пару минут, но только на платформе 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);
});
}
}
}
Вопросы
- Эта проблема связана с тем, как я обновляю таблицу или базовую ошибку?
- Более эффективные способы обновления таблицы?