为了账号安全,请及时绑定邮箱和手机立即绑定

这是使用执行器服务实现多线程的正确方法吗?

这是使用执行器服务实现多线程的正确方法吗?

郎朗坤 2022-06-08 16:25:51
我正在尝试使用执行程序服务来教自己使用多线程,并且想知道在下面实现我的代码的最佳实践是什么-我正在阅读文本文件目录并检查字符/单词-如果我所做的只是通过文件列表对每个线程进行处理,我也很困惑是否正在使用多个线程。是否同时处理多个文件?主班public class Application {    private long totalCharacterCount;    private long totalLineCount;    private final File[] fileList;    private final static String _DIRECTORY = "src//documents";    public Application(String directory){        fileList = new File(directory).listFiles();    }    public synchronized File[] getFileList(){        return fileList;    }    public static void main(String[] args) throws InterruptedException, ExecutionException {           ExecutorService executor = Executors.newFixedThreadPool(4);          Application x = new Application(_DIRECTORY);          for(File file : x.getFileList()){               Future<FileReadings> response = executor.submit(new Process(file));               x.totalCharacterCount += response.get().characterCount;               x.totalLineCount += response.get().lineCount;          }          System.out.println("Total lines in all documents: " + x.totalLineCount);          System.out.println("Total characters in all documents: " + x.totalCharacterCount);          executor.shutdown();    }}进程类public class Process implements Callable<FileReadings> {    private FileReadings object;    private File file;    public Process(File file){        FileReadings obj = new FileReadings();        this.object = obj;        this.file = file;    }    public void CountCharacters(File file){        int count = 0;        try {            BufferedReader reader = Files.newBufferedReader(file.toPath());            while(reader.read() != -1){                count++;            }            object.characterCount = reader.read();        } catch (IOException ex) {            ex.printStackTrace();        }            object.characterCount = count;    }
查看完整描述

1 回答

?
慕田峪4524236

TA贡献1875条经验 获得超5个赞

不。这不是正确的方法。您提交一个进程,然后通过调用get()未来,您阻塞并等待它完成,因此它实际上是一个同步处理。有两种方法可以进行并行、异步处理:


1)invokeAll()


这是更简单的方法,但它需要您提前创建所有流程实例,因此这取决于您要执行多少并行任务(如果您有数百万个,您可能会达到内存限制)。创建流程后,您可以立即将它们提交给执行者。它将并行执行所有任务(根据线程池大小)并在所有任务完成后返回。


      List<Callable<FileReadings>> tasks = new Arraylist<>();

      for (File file : x.getFileList()) {

           tasks.add(new Process(file));

      }

      // submit all processes at once. they will be processed in parallel 

      // this call blocks until all tasks are finished

      List<Future<FileReadings>> responses = executor.invokeAll(tasks);

      // at this point all processes finished. all get() will return immediately

      for (Future<FileReadings> response : responses) {

           x.totalCharacterCount += response.get().characterCount;

           x.totalLineCount += response.get().lineCount;

      }

2)submit()


当您创建一个进程并立即提交它时,此解决方案更具可扩展性,因此内存需求是恒定的(不包括执行程序)。但是,您需要自己管理响应:


      List<Future<FileReadings>> responses = new ArrayList<>();

      for (File file : x.getFileList()) {

           responses.add(executor.submit(new Process(file)));

      }

      // at this point all processes submitted but not finished.

      // need to check which is finished at intervarls

      while (responses.isEmpty() == false) {

          Thread.sleep(1000);  // allow some processing time for tasks

          // ListIterator allows removing items

          ListIterator<Future<FileReadings>> itr = responses.listIterator();

          while (itr.hasNext()) {

               Future<FileReadings> response = itr.next();

               // if task is complete, get it and remove from list

               if (response.isDone()) {

                   x.totalCharacterCount += response.get().characterCount;

                   x.totalLineCount += response.get().lineCount;

                   itr.remove();

               }

          }

      }


查看完整回答
反对 回复 2022-06-08
  • 1 回答
  • 0 关注
  • 122 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号