线程池中的多个线程在同一个List中写入数据

时间:2015-07-12 12:26:52

标签: java multithreading concurrency thread-safety

我在我的threadPool中运行了多个线程。每个线程读取一个巨大的文件并从List中返回此文件中的数据。

代码如下:

class Writer{


   ArrayList finalListWhereDataWillBeWritten = new Array<Integer>()
   for(query q : allQueries){ //all the read queries to read file

      threadPool.submit(new GetDataFromFile(fileName,filePath));        

   }//all the read queries have been submitted.

}

现在我知道以下代码部分会出现在我的代码中的某些部分,但我不知道将它放在何处。 因为如果我将submit()放在for循环之后,它就不会添加它,因为每个文件都非常庞大,可能还没有完成处理。

synchronized(finalListWhereDataWillBeWritten){

  //process the data obtained from single file and add it to target list 
      finalListWhereDataWillBeWritten.addAll(dataFromSingleThread); 

}

所以任何人都可以告诉我,我在哪里放置这段代码以及我需要做些什么来确保关键部分问题不会发生。

class GetDataFromFile implements Runnable<List<Integer>>{

   private String fileName;
   private String filePath;

   public List<Integer> run(){
       //code for streaming the file fileName 
       return dataObtainedFromThisFile;
   }

}

我是否需要在我的代码中使用wait() / notifyAll()方法,因为我只是在线程中并行地读取文件中的数据并将它们放在共享列表中

2 个答案:

答案 0 :(得分:3)

您应该简单地实现Callable<List<Integer>>并将其提交给JDK的标准Executor服务,而不是重新发明轮子。然后,当期货完成时,您将结果收集到列表中。

final ExecutorService threadPool = 
    Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
final List<Future<List<Integer>>> futures = new ArrayList<>();
for(query q : allQueries) {
  futures.add(threadPool.submit(new GetDataFromFile(fileName, filePath)));
}
for (Future<List<Integer>> f : futures) {
    finalListWhereDataWillBeWritten.addAll(f.get());
}

这就是假设你低于Java 8.使用Java 8你当然会使用并行流:

final List<Integer> finalListWhereDataWillBeWritten =
  allQueries.parallelStream()
            .flatMap(q -> getDataFromFile(q.fileName, q.filePath))
            .collect(toList());

答案 1 :(得分:0)

更新请考虑Marko提供的更好的答案

如果您想在完成列表工作之前确保所有线程都已完成,请执行以下操作:

import java.util.List;
import java.util.Vector;

public class ThreadWork {

  public static void main(String[] args) {

    int count = 5;
    Thread[] threads = new ListThread[count];
    List<String> masterList = new Vector<String>();

    for(int index = 0; index < count; index++) {
      threads[index] = new ListThread(masterList, "Thread " + (index + 1));
      threads[index].start();
    }
    while(isOperationRunning(threads)) {
      // do nothing
    }

    System.out.println("Done!! Print Your List ...");

    for(String item : masterList){
      System.out.println("[" + item + "]");
    }
  }

  private static boolean isOperationRunning(Thread[] threads) {
    boolean running = false;

    for(Thread thread : threads) {
      if(thread.isAlive()) {
        running = true;
        break;
      }
    }
    return running;
  }
}

class ListThread extends Thread {
  private static String items[] = { "A", "B", "C", "D"};
  private List<String> list;
  private String name;

  public ListThread(List<String> masterList, String threadName) {
    list = masterList;
    name = threadName;
  }

  public void run() {
    for(int i = 0; i < items.length;++i) {
      randomWait();
      String data = "Thread [" + name + "][" + items[i] + "]";
      System.out.println( data );
      list.add( data );
    }
  }

  private void randomWait() {
    try {
      Thread.currentThread();
      Thread.sleep((long)(3000 * Math.random()));
    }
    catch (InterruptedException x) {}
  }
}