【问题标题】:Preventing list objects from being processed twice when using a java threadpool使用java线程池时防止列表对象被处理两次
【发布时间】:2019-03-29 18:39:31
【问题描述】:

假设我有一个包含 10,000 个对象的列表

ArrayList<String> al=new ArrayList<String>();  
al.add("1");  
al.add("2");
al.add("..");  
al.add("10000");

我想使用一个有 20 个线程的线程池来处理这 10,000 个对象。目标是确保我的程序只读取每个对象一次。

由于程序不会标记列表对象已被读取,我能保证每个对象只被处理一次吗?

【问题讨论】:

  • 将所有 10.000 个对象放入 ConcurrentLinkedQueue 中,然后在每个处理线程中,使用 ConcurrentLinkedQueue.poll 检索对象。

标签: java threadpool threadpoolexecutor


【解决方案1】:

我有一个想法,它可能确实很愚蠢。由于您只是尝试读取列表中的对象,如果您应用此策略怎么样。

  1. 列表中有 10000 个元素。
  2. 您有 20 个线程。
  3. 每个线程选取 500 个元素。
  4. 为每个线程分配一个整数 id,例如 1 到 20。
  5. 每个线程都根据其整数 ID 访问元素。
  6. 像线程 1 访问从 0-499。
  7. 类似的线程 2 访问从 500-999 等等。
  8. 这将保证您不会被多个线程读取任何元素。
  9. 这里有一个假设,即所有线程将对元素进行类似类型的处理。

在另一种方法中,您可以做的是,创建一个同步集,每次选择一个元素时,检查集合中是否存在索引,如果不存在,则选择元素并将其索引插入放。这样你就不会选择一个元素两次。

【讨论】:

    【解决方案2】:

    你可以使用这个代码:

    ExecutorService executorService = Executors.newFixedThreadPool(20);
    
    executorService.execute(new Runnable() {
        public void run() {
            //add item in here and remember using sync data
        }
    });
    executorService.shutdown();
    

    【讨论】:

      【解决方案3】:

      将列表分成 20 个部分:

      Map<Integer, List<String>> mapList = al.stream().collect(Collectors.groupingBy(i -> i.hashCode() % 20));
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-12-27
        • 1970-01-01
        • 1970-01-01
        • 2012-04-28
        • 2010-10-30
        • 2014-07-19
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多