我在目录中有一个变量文件列表,我在Java中有不同的线程来处理它们。线程可变,具体取决于当前处理器
int numberOfThreads=Runtime.getRuntime().availableProcessors();
File[] inputFilesArr=currentDirectory.listFiles();
如何跨线程统一拆分文件?如果我做简单的数学运算
int filesPerThread=inputFilesArr.length/numberOfThreads
如果inputFilesArr.length
和numberOfThreads
不能完全相互整除,我可能会遗漏一些文件。这样做的有效方法是什么,以便所有线程的分区和负载均匀?
答案 0 :(得分:2)
以下是对此问题的另一种看法:
ThreaPoolExecutor
。 Here is an example。 这里我做了一个假设,每个要处理的文件是相互独立的,并且它不需要由一个线程处理某一堆文件。
答案 1 :(得分:1)
您可以使用循环算法进行最佳分配。这是伪代码:
ProcessThread t[] = new ProcessThread[Number of Cores];
int i = 0;
foreach(File f in files)
{
t[i++ % t.length].queueForProcessing(f);
}
foreach(Thread tt in t)
{
tt.join();
}
答案 2 :(得分:1)
Producer Consumer模式将优雅地解决这个问题。让一个生产者(主线程)将所有文件放在绑定的阻塞队列中(参见BlockingQueue)。然后让一些工作线程从队列中获取文件并进行处理。
工作(而不是文件)将统一分布在线程上,因为处理完一个文件的线程要求下一个要处理的文件。这样可以避免一个线程只被分配大型文件进行处理的问题,而其他线程只能处理小文件。
答案 3 :(得分:0)
您可以尝试获取每个线程的文件范围(inputFilesArr的开始和结束索引):
if (inputFilesArr.length < numberOfThreads)
numberOfThreads = inputFilesArr.length;
int[][] filesRangePerThread = getFilesRangePerThread(inputFilesArr.length, numberOfThreads);
和
private static int[][] getFilesRangePerThread(int filesCount, int threadsCount)
{
int[][] filesRangePerThread = new int[threadsCount][2];
if (threadsCount > 1)
{
float odtRangeIncrementFactor = (float) filesCount / threadsCount;
float lastEndIndexSet = odtRangeIncrementFactor - 1;
int rangeStartIndex = 0;
int rangeEndIndex = Math.round(lastEndIndexSet);
filesRangePerThread[0] = new int[] { rangeStartIndex, rangeEndIndex };
for (int processCounter = 1; processCounter < threadsCount; processCounter++)
{
rangeStartIndex = rangeEndIndex + 1;
lastEndIndexSet += odtRangeIncrementFactor;
rangeEndIndex = Math.round(lastEndIndexSet);
filesRangePerThread[processCounter] = new int[] { rangeStartIndex, rangeEndIndex };
}
}
else
{
filesRangePerThread[0] = new int[] { 0, filesCount - 1 };
}
return filesRangePerThread;
}
答案 4 :(得分:0)
如果你正在处理I / O,即使有一个处理器,多个线程也可以并行工作,因为当一个线程正在等待read(byte [])时,处理器可以运行另一个线程。
无论如何,这是我的解决方案
int nThreads = 2;
File[] files = new File[9];
int filesPerThread = files.length / nThreads;
class Task extends Thread {
List<File> list = new ArrayList<>();
// implement run here
}
Task task = new Task();
List<Task> tasks = new ArrayList<>();
tasks.add(task);
for (int i = 0; i < files.length; i++) {
if (task.list.size() == filesPerThread && files.length - i >= filesPerThread) {
task = new Task();
tasks.add(task);
}
task.list.add(files[i]);
}
for(Task t : tasks) {
System.out.println(t.list.size());
}
打印4 5
请注意,如果您有3个文件和5个处理器
,它将创建3个线程