0

I have a following situation: Large file with a lot of lines (~100k, logs from server). Each line in this file should be parsed, filtered and disaplayed on UI.

To read data from file I use BufferedReader, wich read lines, parse it and prepare for disaplying. It runs on different thread (THREAD-1) and populates BlockingQueue. In another thread (THREAD-2) runned UIUpdater - it purpose to get line batch from queue and run something line this:

Platform.runLater(() -> logArea.append(batchedLine)); 

Obviously, FX Thread floods and UI is freezes. So, question is: where I can get information about patterns/best practices to resolove this issue?

DVarga
  • 21,311
  • 6
  • 55
  • 60
Ivan
  • 490
  • 1
  • 7
  • 23

1 Answers1

0

It really depends on the control that you want to populate.

Adding lots of nodes to the scene-graph is expensive therefore it will be slow (for example putting Text objects to any container).

I would suggest the usage of a control that was originally designed to display a huge amount of data, like ListView.

In the example, even during the update of the ListView the Button is responsive.

Main.java

public class Main extends Application {

    @Override
    public void start(Stage primaryStage) {

        HBox root = new HBox();
        Scene scene = new Scene(root, 700, 400, Color.WHITE);

        TableView<Person> personsTable = new TableView<Person>();

        TableColumn<Person, String> nameCol = new TableColumn<Person, String>("Name");
        nameCol.setCellValueFactory(new PropertyValueFactory<>("name"));
        personsTable.getColumns().add(nameCol);

        ObservableList<Person> persons = FXCollections.observableArrayList();

        Thread th = new Thread(new Runnable() {

            @Override
            public void run() {
                for (int i = 0; i < 100000; i++) {
                    Person person = new Person();
                    person.setName("Name" + i);
                    person.setAddress("Address" + i);
                    person.setCountry("Country" + i);
                    person.setCourse("Course" + i);
                    persons.add(person);
                    try {
                        Thread.sleep(5);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }

                }

            }
        }) ;

        th.start();

        personsTable.setItems(persons);

        Button b = new Button();
        b.setOnAction(new EventHandler<ActionEvent>() {

            @Override
            public void handle(ActionEvent event) {
                System.out.println("I am printing independently of Person update!");

            }
        });
        root.getChildren().addAll(personsTable, b);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}

Person.java

public class Person {

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddress() {
        return address;
    }

    public void setAddress(String address) {
        this.address = address;
    }

    public String getCountry() {
        return country;
    }

    public void setCountry(String country) {
        this.country = country;
    }

    public String getCourse() {
        return course;
    }

    public void setCourse(String course) {
        this.course = course;
    }

    private String name;
    private String address;
    private String country;
    private String course;

}

User jewelsea has made a really good example on lgging. With little tailoring it could solve your issue.

Community
  • 1
  • 1
DVarga
  • 21,311
  • 6
  • 55
  • 60