当前位置: 首页 > 面试题库 >

使用线程池/线程读取大型txt文件?

越雨泽
2023-03-14
问题内容

关于我的上一个问题,我发布了:

我必须阅读几个非常大的txt文件,并且必须使用多个线程或一个线程来执行此操作,具体取决于用户输入。
假设我有一个主要方法来获取用户输入,并且用户请求一个线程,并希望为该线程处理20个txt文件。我将如何完成?请注意,以下内容不是我的代码或其设置,而是“想法”的含义。

例:

int numFiles = 20;
int threads = 1;

 String[] list = new String[20];
 for(int i = 1; i < 21; i++){
   list[i] = "hello" + i + ".txt";//so the list is a hello1.txt, hello2.txt, ...,  hello20.txt
 }

 public void run(){
 //processes txt file
 }

因此,总而言之,我将如何用一个线程完成此任务? 有20个线程?

用户建议使用threadPools:

当用户指定要使用的线程数时,您将适当地配置池,提交文件读取作业集,并让池对执行进行排序。
在Java世界中,您将使用Executors.newFixedThreadPool工厂方法,并将每个作业作为Callable提交。这是IBM关于Java线程池的文章。

所以现在我有了一个名为sortAndMap(String x)的方法,该方法接受一个txt文件名并进行处理,对于上面的示例,

Executors.newFixedThreadPool(numThreads);

如何将其与threadPools配合使用,以使上面的示例可行?


问题答案:

好吧,请允许我,因为我需要解释一些事情。

首先,除非您有多个磁盘或一个SSD磁盘,否则建议不要使用多个线程来读取磁盘。关于此主题的许多问题已经发布,结论是相同的:使用多个线程从单个机械磁盘读取将损害性能而不是提高性能。

发生上述情况是因为磁盘的机械头需要继续寻找下一个读取位置。使用多个线程意味着当每个线程都有机会运行时,它将把磁头定向到磁盘的不同部分,从而使磁头在磁盘区域之间的反射效率很低。

处理多个文件的公认解决方案是具有一个生产者(阅读器线程)-多个使用者(处理线程)系统。在这种情况下,理想的机制是线程池,其中线程充当生产者并将任务放入池队列中,以供工人处理。

像这样:

int numFiles = 20;
int threads = 4;

ExecutorService exec = Executors.newFixedThreadPool(threads);

for(int i = 0; i < numFiles; i++){
    String[] fileContents = // read current file;
    exec.submit(new ThreadTask(fileContents));
}

exec.shutdown();
exec.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
...

class ThreadTask implements Runnable {

   private String[] fileContents;

   public ThreadTask(String[] fileContents) {
        this.fileContents = fileContents;
   }

   public void run(){
      //processes txt file
   }
}


 类似资料:
  • 主要内容:一、MySql中的线程,二、主要方式,三、源码流程,四、总结一、MySql中的线程 在mysql中,每一个连接上来,就会分配给一个相关的THD数据类。在前面的分析中可以看到,连接器(Connectors)连接到的直接就是连接池,在连接池的线程处理中分为三部分,即一对一(一个连接对应一个线程),多对一(多个连接对应一个线程)和线程池(多对多)。 线程池和线程可以针对不同的具体场景来处理具体的事务,这样既兼顾了效率又提高了适应性,对于新手来说,这就是设计的一个

  • 每个人我对使用线程池有一个误解。实际结果与该类的API描述不同。当我在线程池中使用时,它不重用线程,线程池等待构造函数中设置的KeepAliveTime,然后杀死这个线程并创建一个新线程。当我将KeepAliveTime设置为较小值时,比如1秒或更短,它会删除一个线程并重新创建它,但如果我设置一分钟,则不会创建新线程,因为不允许创建,队列已经满,所以所有任务都会被拒绝,但KeepAliveTime

  • 有没有可能使用一组线程池来共享大型线程池中的线程,而不是创建新的线程? 在我们的RESTful API应用程序中,一个请求可能涉及多个并行任务。为了提高性能,我们希望在具有固定数量(比如200个)线程的线程池中执行并行任务。但是我们也希望限制每个请求可以使用的最大线程数。所以我在想,如果有可能为每个请求创建一个具有最大池大小的子线程池,它不会自己创建线程,而是尝试从全局线程池中获取一个新线程,并在

  • 接收到数据时回调此函数,发生在worker进程中。函数原型: function onReceive(swoole_server $server, int $fd, int $reactor_id, string $data); $server,swoole_server对象 $fd,TCP客户端连接的唯一标识符 $reactor_id,TCP连接所在的Reactor线程ID $data,收到的数

  • 问题内容: 我有一个固定的线程池,我可以将任务提交给该线程池(限制为 5个 线程)。如何找出这 5个 线程中的哪一个执行我的任务(例如“第3 个 线程中的第3 个 线程正在执行此任务”)? 问题答案: 使用:

  • 主要内容:1 内置线程池,1.1 newFixedThreadPool,1.2 newCachedThreadPool,1.3 newScheduledThreadPool,1.4 newSignalThreadExecutor,2 默认线程工厂,3 Runnable转换为Callable,4 总结详细介绍了Executors线程池工具类的使用,以及四大内置线程池。 Executors可以看作一个工具类,里面提供了好多静态方法,这些方法根据用户选择返回不同的内置线程池实例,或者返回线程工厂,或者