将数据库记录集流式传输给多个线程工作者

时间:2014-06-28 22:36:11

标签: java database multithreading recordset dispatch

我有一个流程需要从数据库传输数据并将记录传递到外部服务器进行处理,然后将结果返回到存储在数据库中。

Get database row from table A
Hand off to external server
Receive result
insert database row into table B

目前这是一个单线程操作,瓶颈是外部服务器进程,因此我希望通过使用外部服务器进程的其他实例来处理请求来提高性能。

Get 100 database rows from table A   
  For each row
    Hand off to external server 1
    Receive Result
    insert database row into table B 
In parallel get 100 database rows from table A
  For each row
    Hand off to external server 2
    Receive Result
    insert database row into table B

问题1 我一直在调查Java线程池,并以这种方式将记录分派到外部服务器,但是我不确定如何在没有工作人员拒绝新任务的情况下尽快从数据库中获取记录。可以用线程池来完成吗?应该用什么架构来实现这个目标?

问题2 目前,我已经使用批处理语句优化了数据库插入,并且只处理了2000条记录后才执行。是否有可能在工人中采用类似的方法?

非常感谢任何帮助构建此问题的解决方案。

1 个答案:

答案 0 :(得分:0)

根据您的评论,我认为关键是控制待处理任务的数量。您有几种选择:

  1. 对数据集中的记录数进行估算。然后,确定将产生合理数量任务的批量大小。例如,如果要将待处理任务计数限制为100.然后,如果您有100K记录,则批处理大小可以为1K。如果您有1Mil记录,则将批量大小设置为10K。

  2. 将自己有界的BlockingQueue提供给线程池。如果您以前没有这样做过,那么在这样做之前,您可能应该仔细研究java.util.concurrent包。

  3. 或者你可以使用java.util.concurrent.Semaphore,它比用户提供的队列更简单:

    • 声明具有待处理任务计数限制的信号量

    Semaphore mySemaphore = new Semaphore(max_pending_task_count);

    • 由于您的任务生成很快,您可以使用单个线程生成所有任务。在你的任务生成线程中:
  4. 
        while(hasMoreTasks()) {
            // this will block if you've reached the count limit
            mySemaphore.acquire(); 
            // generate a new task only after acquire
            // The new task must have a reference to the Semaphore
            Task task = new Task(..., mySemaphore);
            threadpool.submit(task);
        }
        // now that you've generated all tasks,
        // time to wait for them to finish. 
        // you may have a better way to detect that, however
        while(mySemaphore.availablePermits() < max_pending_task_count) {
            Thread.sleep(some_time);
        }
        // now, go ahead dealing with the results
    
    • 在您的任务主题中:
        
        public void run() {
            ...
            // when finished, do a release which increases the permit 
            // by 1 and inform your task generator thread to produce 1 more task
            mySemaphore.release();
        }