2

フォルダー内の多数のファイルを読み取り、スレッドを使用して同時に処理しようとしています。

プログラムの構造は次のようになります。

// Assuming there are 5 files in the directory

// creating the threads
ExecutorService pool = Executors.newFixedThreadPool(5)
ExecutorCompletionService service = new ExecutorCompletionService(pool)

directory.listFiles().each { eachFile ->
   service.submit(new FileReader(eachFile, param2))
}


// the FileReader class
class FileReader implements Callable {
    File file
    String param
    FileReader(File file, String param){
        this.file = file
        this.param = param
    }

   Object call(){
      LOG.info("Processing file" + filePath)
      ConfigInfo configInfo = new ConfigInfo()
  configInfo.setFilePath(filePath);
  configInfo.setReaderUid(readerUid);
  configInfo.setPatternsMap(patternsMap);
  new LogfileDataProcessor(configObject, param).processFileContent()
   }

}

ここで call メソッドは別のオブジェクトを作成し、そのメソッドを呼び出します。

しかし、奇妙なことに、呼び出しメソッドでいくつかの行を実行した後、プログラムが終了します(その最後のステートメントに到達しません)。私はここで混乱しています。誰かが何が起こっているのかに光を当てることができますか. 私を助けてください

4

2 に答える 2

1

スレッドが終了するまでプログラムを待つ必要があります。たとえば、これには CountDounLatch を使用できます。

CountDownLatch latch = new CountDownLatch(numberOfFilesInDirectory);

directory.listFiles().each { eachFile ->
   service.submit(new FileReader(eachFile, param2))
}

latch.await();


// And in your Callable:
class FileReader implements Callable {
File file
String param
FileReader(File file, String param){
    this.file = file
    this.param = param
}

public Object call() {
    try {
    LOG.info("Processing file" + filePath)
    ConfigInfo configInfo = new ConfigInfo()
    configInfo.setFilePath(filePath);
    configInfo.setReaderUid(readerUid);
    configInfo.setPatternsMap(patternsMap);
    new LogfileDataProcessor(configObject, param).processFileContent();
    } finally {
        latch .countDown();
    }
}

コンストラクターの引数としてラッチをスレッドに渡すことができます。

于 2012-05-16T05:49:28.680 に答える
0

まず、callメソッド内のすべての行ではなく数行しか実行されていないことをどうやって知るのでしょうか? あなたが投稿したコードでそれが起こっているのを見る唯一の方法は、そのConfigInfoオブジェクトの作成が例外をスローすることです。

あなたが説明しているシナリオを再現しようとしましたがCallable、作業を新しいデーモンにオフロードした場合にのみ、プログラムを終了させることができましたThread。私のSSCCEについては以下を参照してください。呼び出しをそのままにしておくかどうかに応じthread.setDaemon( true );て、プログラムはすべてThreadの s が実行された後に正常に終了するか、出力がコンソールに書き込まれる前に終了します。

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ExecutorServiceDemo {
  private static ExecutorService pool = Executors.newFixedThreadPool( 5 );

  private static void createAndExecuteThreads(){
    for( int i =0; i< 5; i++ ){
      pool.submit( new DummyCallable( "Callable " + i ) );
    }
  }

  public static void main( String[] args ) {
    createAndExecuteThreads();
    pool.shutdown();
  }
  private static class DummyCallable implements Callable<Object>{
    private final String message;

    private DummyCallable( String amessage ) {
      message = amessage;
    }

    @Override
    public Object call() throws Exception {
      Runnable runnable = new Runnable() {
        @Override
        public void run() {
          try {
            Thread.sleep( 5000 );
            System.out.println( "message = " + message );
          } catch ( InterruptedException e ) {
            e.printStackTrace();
          }
        }
      };
      Thread thread = new Thread( runnable );
      thread.setDaemon( true );
      thread.start();
      return null;
    }
  }

}

あなたのnew LogfileDataProcessor(configObject, param).processFileContent()方法で似たようなことをすることは可能ですか?

于 2012-05-16T05:48:21.907 に答える