无法使用线程在代码块中执行所有语句

时间:2012-05-16 05:18:47

标签: java multithreading groovy

我正在尝试读取文件夹中的多个文件并使用线程同时处理它们。

程序的结构如下:

// 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()
   }

}

此处的调用方法创建另一个对象并在其上调用方法。

但奇怪的是,程序在调用方法中执行了一些行后终止(它没有到达其中的最后一个语句)。我在这里很困惑。有人可以对正在发生的事情有所了解。请帮帮我

2 个答案:

答案 0 :(得分:1)

您需要程序等待线程完成。例如,您可以使用CountDownLatch:

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();
    }
}

您可以将latch作为构造函数参数传递给线程。

答案 1 :(得分:0)

首先,您如何知道call方法中只有几行被执行但不是全部?我发现使用您发布的代码发生的唯一方法是创建该ConfigInfo对象会引发异常。

我尝试重现你正在描述的场景,但我只是设法让我的程序退出,如果在Callable我将工作卸载到一个新的守护进程Thread。请参阅下面的SSCCE。根据您是否将thread.setDaemon( true );调用留在其中,程序在执行所有Thread之后很好地完成,或者在将任何输出写入控制台之前完成。

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()方法中执行类似操作?