2013-03-18 89 views
1

我正在制作一个分配任务的程序。我有沟通对象的ArrayList像这样:如何在java中以线程安全方式创建迭代器循环

ArrayList<Workers> 

我通过文件工作我的方式,将其划分为固定大小的块和分派到各个工人。我正在使用迭代器来均匀地将块传递给工作人员。通常比工人更多的块,所以我需要在我的工人周围和周围循环。我如何做到这一点,我现在的解决方案使用像这样的迭代器。

private Worker getNextWorker() { 
    if (workerIterator == null) 
     workerIterator = workers.iterator(); 

    if (!workerIterator.hasNext()) 
     workerIterator = workers.iterator(); 

    return workerIterator.next(); 
} 

我同步的方法,以及这些方法修改的ArrayList但是,这并不使之安全作为另一个线程可以进来和修改迭代器调用之间的集合。因此,我同步整个文件分割过程,使其成为一个大的原子语句。

1)我错过了什么吗?

2)是否有另一个,也许更好的方式,我可以这个循环功能。

+2

你可能会更好地让工人承担任务,而不是将任务交给工人。也就是说,JDK中有几种可用于此类事情的解决方案:Executors和ExecutorService,CompletionService ... – 2013-03-18 22:35:37

+0

为什么不使用ExecutorService? – 2013-03-18 22:39:49

+0

问题在于我所处理的文件很大,我分裂成大块的原因是为了避免内存问题。然而,如果我能以某种方式限制工作池的规模,并且阻止更多的工作直到工人拿出一些东西,这将是完美的。这可能吗? – 2013-03-18 23:13:34

回答

1

您可以启动工作者线程(不含执行程序),并从有界的阻塞队列中获取元素take。读取文件时,您在队列中输入put块。当队列已满时,对put的调用将阻塞,直到工作人员从队列中取出一个任务。如果队列为空,则工作人员将等待,直到任务放入队列中。当您完成处理时,您可以使用工作线程interrupt

或者,您可以将ThreadPoolExecutorbounded blocking queueCallerRunsPolicy一起使用。这样,如果队列未满,任务将被提交执行。如果队列已满,则调用者线程将执行该任务(这给了工作人员处理的时间)。使用这种方法,最多只能有number_of_threads+queue_capacity块,但在主线程正在处理时,某些工作线程可能处于空闲状态。

+0

谢谢你的回答是清晰并且有帮助 – 2013-03-18 23:39:10

2

我建议你不要重新发明轮子,并使用BlockingQueueThreadPoolExecutor结合用于此目的。

+0

谢谢你将看到这个,我想这必须存在 – 2013-03-18 22:52:17

+0

我将如何使用阻塞队列来实现这一点,我可以想到的一种方式是让工作人员在队列中,我拿出一个,阅读文件的块,发送,然后将该工作人员放在队列的后面。它不是真的如何设计模式,但它可能工作? – 2013-03-18 23:09:54

+0

您应该将文件块放入队列并通过Executor处理它们。 [关于阻塞队列和执行程序的文章](http://howtodoinjava.com/2012/10/20/how-to-use-blockingqueue-and-threadpoolexecutor-in-java/) – 2013-03-18 23:12:32