使用CountDownLatch和ExecutorService类在DB中插入100K记录

时间:2016-04-14 17:52:15

标签: java multithreading

我必须从具有超过100K记录的ArrayList在DB中插入一些值。我正在使用下面给出的CountDownLatch和ExecutorService类来一次运行10个线程以提高插入时的性能。我正在调用一个Stored过程,在一些细节处理之后将Employee细节插入到两个不同的表中。这是否符合我的要求?

 public static void writeData(List<Employee> empList) throws SQLException {
    Connection con = null;
    try {
        Class.forName("oracle.jdbc.driver.OracleDriver");
        con = DriverManager.getConnection("jdbc:oracle:thin:@localhost:1521:xe", "system", "oracle");

        final CountDownLatch latch = new CountDownLatch(empList.size());
        ExecutorService taskExecutor = Executors.newFixedThreadPool(10);

        final CallableStatement cstmt = con.prepareCall("{Call Prc_Insert_Employee(?,?,?)}");

        for (int i = 0; i < empList.size(); i++) {
            final Employee emp = empList.get(i);

            Thread worker = new Thread() {
                public void run() {
                    try {
                        cstmt.setString(1, emp.getId());
                        cstmt.setString(2, emp.getName());
                        cstmt.setString(2, emp.getAge());
                        cstmt.executeUpdate();
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                    finally{
                        latch.countDown();
                    }
                }
            };
            taskExecutor.execute(worker);
        }
        taskExecutor.shutdown();
        latch.await();
    } catch (Exception e) {
        System.out.println(e);
    } finally {
        con.close();
    }
}

1 个答案:

答案 0 :(得分:1)

以下是我对您的代码所做的所有评论:

  1. 您应该考虑使用addBatch()代替executeUpdate()来减少数据库与应用程序之间的往返总量,它应该在性能方面有很大帮助,特别是对于远程数据库,也许你甚至不需要使用这种方法使用多个线程。
  2. 我不相信分享您的CallableStatement是一种好习惯。我不认为它是线程安全的,您应该为每个线程使用专用的ConnectionCallableStatement
  3. 您需要调用connection.setAutoCommit(false)来禁用自动提交模式,该模式并不意味着用于加载大量数据。这意味着您需要为每个x存储的记录显式调用connection.commit()
  4. 在您的代码中,您应该使用Runnable而不是Thread,因为它是ExecutorService所期望的。不需要在此处创建线程实例,因为ExecutorServiceRunnable视为Runnable,因此即使您向{{ExecutorService提供了超过10个execute个对象,您也只有10个线程1}}到Returns true if the stream has no errors occurred and is ready of I/O operations. Specifically, returns !fail()
  5. 不需要CountDownLatch,因为它已经被shutdown()方法所涵盖,因为javadoc中提到了它:
  6.   

    启动有序关闭,其中执行先前提交的任务,但不接受任何新任务。