【问题标题】:Multi threading in javajava中的多线程
【发布时间】:2026-01-12 10:20:06
【问题描述】:

如果我有一个包含 4000 字节的文件,我可以同时从该文件中读取 4 个线程吗?每个线程访问文件的不同部分。

线程 1 读取 0-999,线程 2 读取 1000 - 2999,等等。

请举个java例子。

【问题讨论】:

  • 为什么要 4 个线程读取一个 4000 字节的文件?
  • 您为什么要这样做?只有一个文件和一个数据源,因此您可能会增加搜索(在物理驱动器上),这实际上可能会减慢您的过程。另外,请尝试自己开发代码,然后再提出具体问题。这不是一个让其他人为您完成工作的网站,我们希望提供帮助,但您需要证明您至少已经尝试过先为自己解决这个问题。
  • 将文件作为某种数据结构加载到内存中——也许是一个 id 数组。让线程使用数组中的 id。请务必以同步方式访问数组。
  • 我闻起来像是某人的家庭作业。
  • 感觉就像有人在寻找大学作业问题的答案......

标签: java multithreading file-io


【解决方案1】:

文件非常小,加载速度非常快。我要做的是创建一个加载数据的线程安全数据类。然后,每个处理线程都可以从数据类请求一个 ID,并接收一个唯一的 ID,并保证没有其他线程向您的远程服务发送相同的 ID。

通过这种方式,您无需让所有线程访问文件,并试图找出谁读取并发送了哪个 ID。

【讨论】:

    【解决方案2】:

    RandomAccessFileFileChannel 将允许您访问文件中的字节。要等到您的线程完成,请查看CyclicBarrierCountDownLatch

    【讨论】:

    • 想要运行一个批处理文件,其中包含数千个唯一 ID。这每个唯一的 id 将作为请求发送到远程系统。所以我想使用线程并行发送这些请求以加快进程。但是如果我使用多线程,那么所有读取完整数据和重复请求的线程都会发送。所以我想避免这个重复的请求
    • 如果这是您想要做的,如果您将整个文件的数据加载到内存中的数组中,然后生成读取该数组的单独部分的线程(而不是让每个线程打开并读取相同的文件并寻找不同的位置)
    【解决方案3】:

    鉴于问题作者的评论:

    我想运行一个批处理文件,其中 它包含数以千计的唯一 ID。 这每个唯一的 id 将作为 请求远程系统。所以我 想要使用并行发送请求 线程来加快进程。但 如果使用多线程,那么所有 读取完整数据的线程和 重复的请求正在发送。所以我 想要避免这种重复的请求。

    我建议您将文件作为某种数据结构加载到内存中 - 也许是一个 id 数组。让线程使用数组中的 id。请务必以同步方式访问数组。

    如果文件大于您希望在内存中加载的文件,或者文件不断被附加到,则创建一个单一的生产者线程来监视和读取文件并将 id 插入队列类型结构中。

    【讨论】:

      【解决方案4】:

      对不起,这是工作代码。现在我已经自己测试了:-)

      package readfilemultithreading;

      import java.io.BufferedInputStream;
      import java.io.File;
      import java.io.FileInputStream;
      import java.io.IOException;
      import java.util.ArrayList;
      import java.util.List;
      
      public class MultiThreadFileReader
      {
      
          public MultiThreadFileReader(File fileToRead, int numThreads, int numBytesForEachThread)
          {
              this.file = fileToRead;
              this.numThreads = numThreads;
              this.bytesForEachThread = numBytesForEachThread;
              this.bytes = new byte[(int) file.length()];
          }
          private File file;
          private int numThreads;
          private byte[] bytes;
          int bytesForEachThread;
      
          public byte[] getResult()
          {
              return bytes;
          }
      
          public void startReading()
          {
              List<ReaderThread> readers = new ArrayList<ReaderThread>();
              for (int i = 0; i < numThreads; i ++) {
                  ReaderThread rt = new ReaderThread(i * bytesForEachThread, bytesForEachThread, file);
                  readers.add(rt);
                  rt.start();
              }
              // Each Thread is Reading....
              int resultIndex = 0;
              for (int i = 0; i < numThreads; i++) {
                  ReaderThread thread = readers.get(i);
                  while (!thread.done) {
                      try {
                          Thread.sleep(1);
                      } catch (Exception e) {
                      }
                  }
                  for (int b = 0; b < thread.len; b++, resultIndex++)
                  {
                      bytes[resultIndex] = thread.rb[b];
                  }
              }
          }
      
          private class ReaderThread extends Thread
          {
      
              public ReaderThread(int off, int len, File f)
              {
                  this.off = off;
                  this.len = len;
                  this.f = f;
              }
              public int off,  len;
              private File f;
              public byte[] rb;
              public boolean done = false;
      
              @Override
              public void run()
              {
                  done = false;
                  rb = readPiece();
                  done = true;
              }
      
              private byte[] readPiece()
              {
                  try {
                      BufferedInputStream reader = new BufferedInputStream(new FileInputStream(f));
                      if (off + len > f.length()) {
                          len = (int) (f.length() - off);
                          if (len < 0)
                          {
                              len = 0;
                          }
                          System.out.println("Correct Length to: " + len);
                      }
                      if (len == 0)
                      {
                          System.out.println("No bytes to read");
                          return new byte[0];
                      }
                      byte[] b = new byte[len];
                      System.out.println("Length: " + len);
                      setName("Thread for " + len + " bytes");
                      reader.skip(off);
                      for (int i = off, index = 0; i < len + off; i++, index++)
                      {
                          b[index] = (byte) reader.read();
                      }
                      reader.close();
                      return b;
                  } catch (IOException e) {
                      e.printStackTrace();
                  }
                  return null;
              }
          }
      }
      

      这里是使用代码:

      package readfilemultithreading;

      import java.io.File;
      import java.io.FileOutputStream;
      import java.io.IOException;
      
      public class Main
      {
      
          public static void main(String[] args)
          {
              new Main().start(args);
          }
      
          public void start(String[] args)
          {
              try {
                  MultiThreadFileReader reader = new MultiThreadFileReader(new File("C:\\Users\\Martijn\\Documents\\Test.txt"), 4, 2500);
                  reader.startReading();
                  byte[] result = reader.getResult();
                  FileOutputStream stream = new FileOutputStream(new File("C:\\Users\\Martijn\\Documents\\Test_cop.txt"));
                  for (byte b : result) {
                      System.out.println(b);
                      stream.write((int) b);
                  }
                  stream.close();
              } catch (IOException ex) {
                  System.err.println("Reading failed");
              }
          }
      }
      

      我现在可以恢复我的 +1 了吗?-)

      【讨论】:

      • 适用于像 10mb 这样的小文件,但是如果你的文件超过 100mb,你会遇到异常,outofmemoryerror。我知道增加应用程序的堆大小,但如果应用程序达到一定的读取限制并将读取刷新到输出流,这样会更好,这样你就不会遇到内存异常。顺便说一句,读取速度很快,三万行,不到1秒。
      【解决方案5】:

      您必须以某种方式同步对文件的读取访问权限。我建议使用ExecutorService:

      您的主线程从文件中读取 ID,并一次将它们传递给执行器服务。 executor会运行N个线程同时处理N个ID。

      【讨论】: