java - 将 JSON 文件读入集合,最佳实践
问题描述
我正在开发一个 JavaFX 应用程序。我有几个 JSON 文件,我想读取这些文件并将其插入到域对象的集合中。我目前正在使用 Gson 来读取这些文件。我的应用程序目前正在运行,但是在应用程序启动之前有很长的延迟。我认为这是因为我在同一个线程中按顺序读取这些文件。因此,我希望通过引入一些并发来缩短启动时间。我在想如果我能弄清楚如何并行读取文件,它应该会加快启动时间。我对并发的想法很陌生,所以我正在努力学习。不用说,我遇到了一些障碍,似乎无法在网上找到太多信息或示例。
这是我的问题:
- 不确定 JSON 文件读取是否可以在后台线程中完成。
域类使用这些集合来计算并最终在 GUI 中显示值。据我了解,如果您修改 GUI,则必须在 JavaFX 应用程序线程中完成,而不是在后台完成。我不确定加载要在 GUI 中使用的数据是否算作修改 GUI。我不会通过读取 Json 来直接更新任何 GUI 节点,例如 textField.setText("something"),所以我假设不,我不是。我错了吗?
Task> 和 Thread 或 ExecutorService 和 Callable> 有什么区别?一种方法优于另一种方法吗?我都试过了,都失败了。当我尝试使用任务和后台线程时,我会收到 NullPointerException,因为应用程序在读取文件并使用数据初始化之前尝试访问集合。它从太慢变成了太快。SMH。
为了解决这个问题,我听说了 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。我怎么知道它是通过任务处理的?
解决方案
您的应用程序将加速多少取决于这些文件有多大以及有多少文件。您应该知道创建线程也是一项资源消耗任务。我可以想象您有大量文件并且为每个文件创建一个新线程的情况,这甚至可能使您的应用程序初始化速度变慢。如果文件量大或文件数会随时间变化,可以安排一些固定数量的线程池,例如。5 可以同时进行文件读取任务。回到问题,问题是否值得使用单独的线程来读取文件,我会说是的,但前提是您的应用程序有一些初始化工作,可以在不知道这些文件内容的情况下完成。您应该知道,在某个时间点,您可能需要等待文件解析结果。
作为解决问题的一部分,您可以做一些基准测试来检查解析每个文件进程需要多长时间,然后您就会知道什么配置/工作线程数量是最好的。例如。当解析需要 1 秒时,您不会为每个文件创建线程,但如果您有 100 个处理时间为 1 秒的文件,您可以创建一些线程池并平均分配每个线程的作业。
是的
我不知道 JavaFX,但总的来说 Thread 和 Task 的概念是相同的。线程让您确定您正在启动新线程,它是较低级别的抽象。任务是某种更高的抽象,您希望在其中单独运行部分代码,并且异步运行,但您不想知道它将在哪个线程上运行。Task 背后的一些编程语言实际上隐藏了一些线程池。
预加载器很好,因为它们向用户显示一些工作正在后台完成,因此如果应用程序已冻结,他不会担心。另一方面,如果您可以加快初始化过程,那就太好了。您可以加入这两个想法,但请记住,没有人愿意等待很多 :)
推荐阅读
- r - bsModal 适用于 fluidPage 但不能没有它
- html - Nu Html 检查器错误“扩展为回车的数字字符引用。” 使用“”时
- graphql - 在 AWS 上使用 Cloudfoundry 部署的 Hasura GraphQL 引擎上的订阅错误
- java - F 有界多态 Java 中的返回类型
- sql - PostgreSQL 如何查询字符串数组
- asp.net-core-mvc - 从下拉列表中获取选定项目并将其传递给 onClick 事件
- javascript - React 使用仪表板构建 CMS 如何显示隐藏仪表板组件
- swift - 即使在设备旋转之后也约束/居中 CAEmitterLayer
- python - pyrequests 将 dict 值编码为 JSON 中的列表
- r - 为什么 dplyr 过滤器不接受整数数据帧?