0

ディレクトリにファイルの可変リストがあり、それらを処理するために Java にさまざまなスレッドがあります。スレッドは、現在のプロセッサに応じて可変です

int numberOfThreads=Runtime.getRuntime().availableProcessors();

File[] inputFilesArr=currentDirectory.listFiles();

ファイルをスレッド間で均一に分割するにはどうすればよいですか? 次のような簡単な計算をすると

int filesPerThread=inputFilesArr.length/numberOfThreads

inputFilesArr.lengthnumberOfThreadsが互いに正確に割り切れない場合、いくつかのファイルが失われる可能性があります。すべてのスレッドのパーティションと負荷が均一になるように、これを行う効率的な方法は何ですか?

4

5 に答える 5

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();
}
于 2012-12-26T05:35:03.893 に答える
1

Producer Consumer パターンはこれをうまく解決します。1 つのプロデューサー (メイン スレッド) にすべてのファイルをバインドされたブロッキング キューに配置させます ( BlockingQueueを参照)。次に、多数のワーカー スレッドがキューからファイルを取得して処理します。

1 つのファイルの処理が完了したスレッドは、次に処理するファイルを要求するため、作業 (ファイルではなく) がスレッド全体に均一に分散されます。これにより、1 つのスレッドが処理対象の大きなファイルのみを割り当てられ、他のスレッドが処理対象の小さなファイルのみを取得するという問題が回避されます。

于 2012-12-26T06:35:08.517 に答える
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;
}
于 2012-12-26T05:53:18.150 に答える