多线程文件处理和数据库批量插入

时间:2016-06-14 16:42:43

标签: java multithreading threadpool executorservice file-processing

我有一个Java主应用程序,它将逐行读取文件。每行代表订户数据。

name, email, mobile, ...

为每个正在处理的行创建一个订阅者对象,然后使用JDBC将该对象保存在数据库中。

PS:输入文件有大约1500万个用户数据,应用程序大约需要10-12个小时来处理。我需要将此减少到大约2-3小时,因为此任务是迁移活动,我们得到的停机时间大约为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。

1 个答案:

答案 0 :(得分:1)

persistSub(sub)不应立即访问数据库。相反,它应该将sub存储在长度为500-1000的数组中,并且仅当数组已满或输入文件终止时,将其包装在Runnable中并提交给线程池。然后Runnable通过jdbc访问数据库,就像在JDBC Batching with PrepareStatement Object中描述的那样。

更新

如果写入数据库很慢并且输入文件读取速度很快,则可以创建许多带有数据的数组,等待在数据库中写入,并且系统可能会耗尽内存。所以persistSub(sub)应该跟踪分配的数组的数量。最简单的方法是使用允许数量的数组进行Semaphore inbitialized。在分配新数组之前,persistSub(sub)生成Semaphore.aquire()。每个Runnable任务在结束之前生成Semaphore.release()