使用多线程将数百万个数据插入到数据库中

时间:2016-10-26 08:36:06

标签: java multithreading

我正在尝试将数百万个数据行插入数据库。我正在尝试使用ThreadPoolExecutor来实现此目的。我正在为每9000条记录创建一个批处理并将批处理发送到每个线程。在这里,我将ThreadPool Size修改为20.大小增加后,它会失败。如何检查ThreadPoolExecutor中可用的线程数以及如何等待线程池有空闲线程。

听到我的代码,如果我错了,请帮忙。

int threadCount=10;
        ThreadPoolExecutor threadPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(threadCount);
        int i=0;

        StringBuffer sb=new StringBuffer();
        sb.append("BEGIN BATCH");
        sb.append(System.lineSeparator());
        int cnt =metaData.getColumnCount();
        while(rs.next())
        {       
            String query ="INSERT INTO "+table+" ("+columnslist.get(1)+")VALUES("+i;
            for ( int j=1 ; j <= cnt ; j++)
            {
                if(metaData.getColumnTypeName(j).contains("int") || metaData.getColumnTypeName(j).contains("number"))
                {
                        query +=","+ rs.getInt(j);
                }
                else if(metaData.getColumnTypeName(j).contains("varchar") || metaData.getColumnTypeName(j).contains("date") || metaData.getColumnTypeName(j).contains("getTimestamp"))
                {
                        query +=",'"+parseColumnData(rs.getString(j))+"'";
                }
                else
                {
                        query +=",'"+parseColumnData(rs.getString(j))+"'";  
                }
            }
                query +=");";
                sb.append(query);sb.append(System.lineSeparator());
                if(i%9000==0)
                {
                    sb.append("APPLY BATCH");
                    System.out.println(threadPool.getActiveCount());

                    Thread t = new Thread(new ExcecuteTask(sb.toString(),session));
                    threadPool.execute(t);              
                    sb.setLength(0);
                    sb.append("BEGIN BATCH");
                    sb.append(System.lineSeparator());

                }
                i++;
            }
            sb.append("APPLY BATCH");

            Thread t = new Thread(new ExcecuteTask(sb.toString(),session));
            threadPool.execute(t);
             sb.setLength(0);

            threadPool.shutdown();
            while (threadPool.getTaskCount() != threadPool.getCompletedTaskCount())
            {
            }

            System.out.println(table+" Loaded sucessfully");





public class ExcecuteTask implements Runnable 
{
        private String sb;
        private Session session;

        public ExcecuteTask(String s,Session session) 
        { 
            sb = s;
            this.session=session;
        }
        public void run()
        {
            session.executeAsync(sb.toString());
        }
 }

1 个答案:

答案 0 :(得分:1)

您可以通过调用ThreadPoolExecutor方法在getActiveCount中找到活动线程的大致数量。但是你不应该这样做。

来自Java documentation for Executors.newFixedThreadPool

  

创建一个线程池,该线程池重用在共享无界队列中运行的固定数量的线程。在任何时候,最多nThreads线程将是活动的处理任务。如果在所有线程都处于活动状态时提交了其他任务,则它们将在队列中等待,直到线程可用。如果任何线程由于在关闭之前执行期间的故障而终止,则在需要执行后续任务时将使用新的线程。池中的线程将一直存在,直到明确关闭为止。

因此,您应该能够继续向线程池提交任务,并且当线程可用时,它们将被选中并运行。

我还注意到,您将任务包装在Thread个对象中,然后再将它们提交给线程池,这是不必要的。