java - 将 JSON 文件读入集合,最佳实践

标签 java multithreading javafx concurrency javafx-8

我正在开发 JavaFX 应用程序。我有几个 JSON 文件,我想读取这些文件并将其插入到域对象的集合中。我目前正在使用Gson来读取这些文件。我的应用程序当前正在运行,但是在应用程序启动之前有很长的延迟。我认为这是因为我正在同一线程中顺序读取这些文件。因此,我希望通过引入一些并发性来缩短启动时间。我在想如果我能弄清楚如何并行读取文件,它应该会加快启动时间。我对并发的概念很陌生,所以我正在努力学习。不用说,我遇到了一些障碍,并且似乎无法在网上找到太多信息或示例。

这是我的问题:

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

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

  • Task> 和 Thread 或者 ExecutorService 和 Callable> 之间有什么区别?一种方法优于另一种方法吗?我两种都尝试过,但都失败了。当我尝试使用任务和后台线程时,我会收到 NullPointerException,因为应用程序在读取文件并用数据初始化之前尝试访问集合。它从太慢变成了太快。 SMH。

  • 为了解决这个问题,我听说了预加载器。这里的想法是启动某种启动屏幕来延迟,直到资源加载(读取 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。我如何知道它已通过任务处理完所有内容?

    最佳答案

    您的应用程序的加速程度取决于这些文件的大小以及文件的数量。你应该知道创建线程也是一个消耗资源的任务。我可以想象这样的情况:您有大量文件,并且为每个文件创建一个新线程,这甚至可能使您的应用程序初始化速度变慢。 如果文件量很大或文件数量会随时间变化,您可以安排一些恒定数量的线程池,例如。 5个可以同时进行读文件任务。 回到问题,问题是是否值得使用单独的线程来读取文件,我会说是的,但前提是您的应用程序有一些初始化工作,这些工作可以在不知道这些文件的内容的情况下完成。您应该意识到,在某个时间点您可能需要等待文件解析结果。

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

    1. 我不了解JavaFX,但总的来说,线程和任务的概念是相同的。线程让您确定您正在启动新线程,它是较低的抽象级别。任务是某种更高的抽象,您希望单独异步运行部分代码,但您不想知道它将在哪个线程上运行。 Task背后的一些编程语言实际上隐藏了一些线程池。

    2. 预加载器很好,因为它们向用户显示一些工作正在后台完成,因此他不会担心应用程序是否卡住。另一方面,如果您可以加快初始化过程,那就太好了。您可以加入这两个想法,但请记住,没有人愿意等待太久:)

    关于java - 将 JSON 文件读入集合,最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51505351/

    相关文章:

    java - Eclipse自动补全问题

    C# 从多个线程对表执行批量更新,不会出现死锁

    Java 在我的 Java 代码中出现 .setText 错误

    listview - 使用 JSoup 作为服务显示超链接的 ListView

    Java 四舍五入 0.05 钱

    java - 我无法让用户定义的检查异常正常工作

    java - GetRequest 中带有 2 个参数的 SQL 查询

    multithreading - 有多个 channel 与单个共享结构进行通信是否线程安全?

    java - 制作线程的差异?

    从构建的 JRT 模块运行应用程序时,从 URL 构造的 JavaFX 11 javafx.scene.image 抛出 SSLHandshakeException