我需要在多核机器上处理大量(> 1亿)请求(每个请求都是处理数据文件中的一行,并涉及远程系统的一些I / O.虽然详情没关系,具体任务是从一些数据文件加载分布式Hazelcast映射)。执行将通过ThreadPoolExecutor处理。一个线程将读取该文件,然后将数据提交给多个独立的线程以将其放入映射中。该机器有32个核心,因此有足够的可用于并行加载地图。
由于请求数量很多,创建任务并将它们排队到执行程序服务的常用方法是不可行的,因为排队的任务会占用太多内存。
带来了ExecutorCompletionService。有了它,一个任务将在前一个操作完成时提交,通过调用take()
(或poll()
,如果适用)可以知道。当使用执行程序服务的所有线程时,这将正常工作。但是,“加载所有线程”尚未完成。有两个阶段:
填满队列:虽然池中仍有未使用的线程,但是将任务提交给ExecutorCompletionService并且不要等到提交更多
提供队列:一旦线程全部被使用,只需在上一个任务完成后提交任务。因此,行将尽快送达,但不会更快,也不会排队。
以上可以编码,但我想知道上面的逻辑是否已经实现,我不知何故错过了它。我问,因为它看起来是一种常见的情况。
答案 0 :(得分:4)
您可以在创建BlockingQueue
时指定ThreadPoolExecutor
实施。如果您要避免的是创建多余的Runnable
个对象,那么您可以使用有界BlockingQueue
,例如ArrayBlockingQueue
有一个线程将项目推送到队列,当队列达到容量时,该队列将被阻止。
答案 1 :(得分:-1)
如果我理解你的要求,(如果我错了就纠正我)那么你需要一个机制,其中有几个任务,你需要最多n
个任务并行执行,其他任务应该在队列中等待,但是一旦你提交了一个任务,那么你就不想闲逛或让线程提交任务忙碌,它可以继续它的工作
对于相同的情况,我们使用LinkedBlockingQueue
和Thread
的混合,我相信一个简单的函数可以帮助您理解,
private final LinkedBlockingQueue<YourTaskObjType> EnqueuedTasks;
private void initTasksProcessingThreads(int numberOfThreads)
{
EnqueuedTasks= new LinkedBlockingQueue<YourTaskObjType>();
for (int i = 0; i < numberOfThreads; i++)
{
// each thread will run forever and process incoming
//Change requests
Thread worker = new Thread(new Runnable()
{
public void run()
{
while (true)
{
try
{
YourTaskObjType task = EnqueuedTasks.take(); //This will wait infinitely until tasks are available
PerformTask(task); //Your function which will perform the task operation
}
catch (InterruptedException e)
{
Thread.currentThread().interrupt();
return;
}
catch(Exception e)
{
e.printStackTrace();
}
}
}
});
worker.start();
}
}
然后,您可以使用一个简单的函数将任务添加到LinkedBlockingQueue
,
public void AddTask(YourTaskObjType TaskObj)
{
EnqueuedTasks.put(TaskObj);
}