当前位置: 首页 > 知识库问答 >
问题:

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

何哲
2023-03-14

我有多个线程在我的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.

}

现在我知道以下代码段将出现在我的代码中的某个位置,但我不知道将其放置在哪里。因为如果我在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个答案

汪信鸥
2023-03-14

更新请考虑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) {}
  }
}
漆雕彬彬
2023-03-14

与其重新发明轮子,不如简单地实现Callable

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

这都是假设你低于Java8。对于Java 8,您当然会使用并行流:

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

 类似资料:
  • 问题内容: 我是Python多线程的新手,目前正在编写一个附加到csv文件的脚本。如果要向提交多个线程,则将行追加到csv文件中。如果附加是这些线程执行的唯一与文件相关的操作,我该怎么做才能保证线程安全? 我的代码的简化版本: 我的线程类是: 我应该设置一个单独的单线程执行程序来处理编写,还是担心我是否只是追加? 编辑:我应该详细说明,下一次附加文件之间的分钟之间,写操作发生的时间可能会相差很大,

  • 面试问题 比如说,我们有一个在Employee表中有200万条记录的表,我们需要削减每个员工10%的工资(需要做一些处理),然后将其保存回collection。你怎样才能有效地做到这一点。 我问他,我们可以使用executor框架来创建多个线程,这些线程可以从表中获取值,然后我们可以处理并将其保存到列表中。 然后他问我,你将如何检查一个记录是否已经被处理,我不知道(如何做)。 甚至我也不确定我是否

  • 问题内容: 在多个线程上调用Java 对象是否安全?输出会正确序列化吗? 澄清: 在我的情况下,类记录器拥有FileOutputStream引用,并且多个线程可以调用记录器写,从而格式化输出并调用FileOutputStream写。 我应该同步记录器的写方法以保证来自多个线程的消息不会混合吗? 问题答案: 不能多次打开文件,因此答案是否定的。 在看到您的编辑之后,是的,您应该在记录器中引入同步,以

  • 我对连接池的理解是;如果connectionstring完全相同,那么我们重用该连接,而不是建立新的连接。 我的问题是,我正在为并行处理创建许多线程。在这个“虚拟”程序中,我创建了500个线程,并让线程池函数处理这些线程。 步骤是: > < li> 每个线程在SQL中创建一个更新表。(说明更新的时间戳) 然后线程Hibernate1到10秒(随机)。 最后,线程在 SQL 中进行另一次更新(说明结

  • 当我尝试通过启动不同的线程来执行所有同步方法时,我在一个类中有三个同步方法,我看不到同步的输出,在对象上没有获得锁 公共类DisplayMessage{ }线程类: 公共类 MyThread 扩展了线程 { }Thread2类:公共类MyThread2扩展线程{ } 线程 3 类: 包装Synchronization.classlock; 公共类MyThread3扩展线程{ } 使用main方法生

  • 本文向大家介绍C#线程处理系列之线程池中的I/O线程,包括了C#线程处理系列之线程池中的I/O线程的使用技巧和注意事项,需要的朋友参考一下 一、I/O线程实现对文件的异步  1.1  I/O线程介绍: 对于线程所执行的任务来说,可以把线程分为两种类型:工作者线程和I/O线程。 工作者线程用来完成一些计算的任务,在任务执行的过程中,需要CPU不间断地处理,所以,在工作者线程的执行过程中,CPU和线程