我有一个 Java 主应用程序,它将逐行读取文件。每行代表订阅者数据。
name, email, mobile, ...
为正在处理的每一行创建一个订阅者对象,然后使用 JDBC 将这个对象保存在数据库中。
PS:输入文件包含大约 1500 万个订阅者数据,应用程序需要大约 10-12 小时来处理。我需要将其减少到大约 2-3 小时,因为此任务是一项迁移 Activity ,我们得到的停机时间约为 4-5 小时。
我知道我需要使用多线程/线程池,可能是Java原生的ExecuterService。但我也被要求进行批量更新。假设采用 50 或 100 个工作线程的线程池并批量更新 500-1000 个订阅者。
我熟悉使用 ExecuterService,但没有找到一种可以在其中包含批量更新逻辑的方法。
我的整体应用程序代码如下所示:
while (null != (line = getNextLine())) {
Subscriber sub = getSub(line); // creates subscriber object by parsing the line
persistSub(sub); // JDBC - PreparedStatement insert query executed
}
需要知道一种方法,可以使用多个线程并使用批量更新或任何可用于此类情况的现有框架或 Java API 来更快地处理它。
最佳答案
persistSub(sub)
不应立即访问数据库。相反,它应该将 sub
存储在长度为 500-1000 的数组中,并且仅当数组已满或输入文件终止时,将其包装在 Runnable
中并提交给一个线程池。然后,Runnable
通过 jdbc 访问数据库,如 JDBC Batching with PrepareStatement Object 中所述。 .
更新
如果写入数据库很慢而读取输入文件很快,则可能会创建许多包含数据的数组等待写入数据库,并且系统可能会耗尽内存。因此,persistSub(sub) 应该跟踪分配的数组的数量。最简单的方法是使用 Semaphore用允许的数组数量进行初始化。在分配新数组之前,persistSub(sub)
会生成 Semaphore.aquire()
。每个 Runnable
任务在结束之前都会生成 Semaphore.release()
。
关于java - 多线程文件处理和数据库批量插入,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37817746/