0

大きな csv ファイル (328 MB) を読み取って処理する必要があります。各行の処理には、Web サービスの呼び出しも含まれます。

初めて ThreadPoolExecutor を使用しています。私のロジックは、csv から 100 行ごとに吐き出し、各行を実行して処理し、結果を templ ファイルに書き込むスレッドを作成します。すべてのスレッドが終了したら、一時ファイルを読み取り、comined 出力ファイルを作成します。

ファイルを分割してスレッドを作成する私の方法

private List<Thread> invokeWS(String csvFilename, String tempFolder) {

    List<Thread> processCsvThreadList = new ArrayList<Thread>();

    //Thread Pool Executer


    int corePoolSize = 3;
    int maximumPoolSize = 6;
    long keepAliveTime = 10;
     ThreadFactory threadFactory = Executors.defaultThreadFactory();


    ThreadPoolExecutor thrdPoolEx = new ThreadPoolExecutor(corePoolSize,
            maximumPoolSize, keepAliveTime, TimeUnit.SECONDS,
            new ArrayBlockingQueue<Runnable>(2));


    try {
        BufferedReader bfr = new BufferedReader(new FileReader(csvFilename));
        String line = "";
        int i = 0;
        line = bfr.readLine();
        Thread csvThread;
        List<String> rowList = new ArrayList<String>();


        do {
            line = bfr.readLine();
            if (line != null) {

                rowList.add(line);
                i++;

                if (i % 100 == 0) {

                    csvThread = new Thread(new ProcessCsvRow(rowList,
                            tempFolder));
                    csvThread.start();
                    thrdPoolEx.execute(csvThread);

                    rowList = new ArrayList<String>();
                    processCsvThreadList.add(csvThread);
                }

            } else {
                if (null != rowList && !rowList.isEmpty()) {

                    csvThread = new Thread(new ProcessCsvRow(rowList,
                            tempFolder));
                    csvThread.start();
                    thrdPoolEx.execute(csvThread);

                    processCsvThreadList.add(csvThread);
                }
                break;
            }
        } while (true);




    } catch (FileNotFoundException fnf) {
        fnf.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    finally{
        thrdPoolEx.shutdown();
        }
    return processCsvThreadList;
}

私の ProcessCsvRow クラス

public class ProcessCsvRow implements Runnable {

private List<String> csvRowsList;
private String tempDir;

public ProcessCsvRow(List<String> csvRowsList, String tempDir) {

    this.csvRowsList = csvRowsList;
    this.tempDir = tempDir;
}

@Override
public void run() {
    UUID idOne = UUID.randomUUID();
    FileWriter fw = null;
    BufferedWriter bufferedWriter = null;
    try {
        String res = "";
        fw = new FileWriter(new File(tempDir + "\\" + idOne.toString()+FilePropConstants.FILE_NAME_EXT_TMP));

        bufferedWriter = new BufferedWriter(fw);
        SentimentAnalyzer sentimentAnalyzer = new SentimentAnalyzer();

        for (String csvRow : csvRowsList) {
            //calling webservice for each row

            res = sentimentAnalyzer.invokeSentWS(csvRow);
            bufferedWriter.write(res);


        }

    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        try {
            if (bufferedWriter != null) {
                bufferedWriter.flush();
                bufferedWriter.close();
            }
            if (fw != null) {
                fw.close();
            }

        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}

}

問題は、5 行の csv の場合、一時ファイルが 1 つ作成されるはずですが、このプログラムを実行すると、間違った 2 つの一時ファイルが生成されることです。これは論理的な問題ではなく、ThreadPoolExecuter を実装した方法にあると強く信じています。

どんな助けでも大歓迎です。

4

2 に答える 2

1

スレッドを作成するべきではなく、スレッド プールを直接作成する必要もありません。

試す

ExecutorService es = Executors.newFixedThreadPool(8);

es.submit(runnable); // not threads

ところで、各スレッドは独自の出力ファイルを作成するか、共有ファイルをロックする必要があります。または、 Callable を送信して、ログに記録したいものを送信スレッドに返すようにすることができます。

于 2013-05-09T06:17:20.230 に答える
1

これは、自分でスレッドを開始し、エグゼキューターに実行を依頼しているためです。

変化する:

csvThread = new Thread(new ProcessCsvRow(rowList, tempFolder));
csvThread.start();
thrdPoolEx.execute(csvThread);

rowList = new ArrayList<String>();
processCsvThreadList.add(csvThread);

に:

csvThread = new Thread(new ProcessCsvRow(rowList, tempFolder));
thrdPoolEx.execute(csvThread);

rowList = new ArrayList<String>();
processCsvThreadList.add(csvThread);
于 2013-05-09T06:19:30.517 に答える