将JSON文件读入集合,这是最佳实践

问题描述 投票:0回答:1

我正在研究JavaFX应用程序。我有几个JSON文件,我想阅读并插入到域对象的集合中。我目前正在使用Gson阅读这些文件。我的应用程序目前正在运行,但是,在应用程序启动之前有很长的延迟。我认为这是因为我正在顺序读取这些文件并在同一个线程中。因此,我希望通过引入一些并发来增强启动时间。我在想如果我能弄清楚如何并行读取文件,它应该加快启动时间。我对并发的想法很新,所以我正在努力学习。毋庸置疑,我遇到了一些障碍,似乎无法在网上找到太多信息或示例。

这是我的问题:

  1. 不确定JSON文件读取是否可以在后台线程中完成。

域类使用这些集合来计算并最终在GUI中显示值。根据我的理解,如果修改GUI,则必须在JavaFX Application线程中完成,而不是在后台完成。我不确定在GUI中使用的加载数据是否算作修改GUI。我不是通过阅读Json直接更新任何GUI节点,如textField.setText(“something”),所以我会假设不,我不是。我错了吗?

  1. Task>和Thread或ExecutorService和Callable>之间有什么区别?一种方法比另一种方法更受欢迎吗?我试过了两次都失败了。当我尝试使用任务和后台线程时,我会得到一个NullPointerException,因为应用程序在读取文件并使用数据初始化之前尝试访问该集合。它从太慢到太快。 SMH。
  2. 为了解决这个问题,我听说过Preloaders。这里的想法是启动某种启动屏幕,直到资源加载(读取JSON文件)完成,然后进入主应用程序。但是,这里的示例或信息非常稀少。我正在使用Java 10和IntelliJ,所以我可能已经陷入了百万分之一的利基市场。

我不是要求任何人为我解决我的问题。我只是有点失落,不知道在哪里或如何进行。如果需要,我会很乐意分享细节,但我认为我的问题在这一点上仍然是概念性的。

帮帮我StackOverflow你是我唯一的希望。

编辑:代码示例:

public class Employee {

  private List<Employee> employeeList;

  public Employee() {
    employeeList = new ArrayList<>();
    populateEmployees();
  }

  private final void populateEmployees() {
    Task<Void> readEmployees = new Task<>() {
      @Override
      protected Void call() throws Exception {
        System.out.println("Starting to read employee.json"); // #1
        InputStream in = getClass().getResourceAsStream("/json/employee.json");
        Reader reader = new InputStreamReader(in);
        Type type = new TypeToken<List<Employee>>(){}.getType();
        Gson gson = new Gson();
        employeeList.addAll(gson.fromJson(reader, type));
        System.out.println("employeeList has " + employeeList.size() + " elements"); // #2
        return null;
      }
    };
    readEmployees.run();
    System.out.println(readEmployees.getMessage());  // #3
  }
}

我看到#1打印到控制台,从未#2或3.我怎么知道它通过任务处理完毕?

java multithreading javafx concurrency javafx-8
1个回答
1
投票

您的应用程序将加快多少取决于这些文件的大小和文件的数量。您应该知道创建线程也是消耗资源的任务。我可以想象你有大量文件的情况,而且每个人都在创建一个新的线程,甚至可能使你的应用程序初始化速度变慢。如果文件数量大或文件数量可以及时更改,可以安排一些常数的线程池,例如。 5可以同时读取文件任务。回到问题和问题是值得使用单独的线程来读取文件,我会说是,但只有你的应用程序有一些初始化工作,可以在不知道这些文件的内容的情况下完成。您应该知道,在某个时间点您可能需要等待文件解析结果。

作为解决问题的一部分,您可以做一些基准测试来检查解析每个文件进程需要多长时间,然后您就会知道哪些配置/工作线程数量最好。例如。在解析需要1秒时,您不会为每个文件创建线程,但如果您有100个1秒处理时间的文件,则可以创建一些线程池并平均分配每个线程的作业。

  1. 我不了解JavaFX,但一般来说Thread和Task的概念是一样的。线程为您提供了开始新线程的证明,它是较低的抽象级别。任务是某种更高的抽象,你想要单独运行部分代码,并且异步运行,但你不想知道它将运行哪个线程。 Task背后的一些编程语言实际上隐藏了一些线程池。
  2. 预加载器很好,因为它们向用户显示一些工作正在后台完成,因此如果应用程序已冻结,他也不会担心。另一方面,如果你可以加快初始化过程,它会很棒。你可以加入这两个想法,但请记住,没有人愿意等待很多:)
© www.soinside.com 2019 - 2024. All rights reserved.