在Java中的不同线程中同时从集合中读取和写入

时间:2019-02-16 09:22:05

标签: java collections

这是场景:
我有3条车道想要从中移动箱子。每个框都有一个groupId。这样车道将被分配到一个组。
因此,当我收到具有唯一groupId的第一个移动请求时,我将创建一个列表并将此请求添加到该列表中,然后开始处理该列表。如果我收到另一个具有相同groupId的请求,则必须添加到同一列表中
(此列表用于处理不同线程中的请求),
否则创建一个新列表并分配一个新车道并开始处理。
请提出一个Java集合,以帮助有效地实现此目标。
任何帮助将不胜感激!

2 个答案:

答案 0 :(得分:0)

如果需要对int lostSheep(const int *friday, size_t sz1, const int* saturday, size_t sz2, int total) { size_t i; for (i = 0; i < sz1; ++i) { total -= friday[i]; } for (i = 0; i < sz2; ++i) { total -= saturday[i]; } return total; } 进行突变并从多个线程中进行读取,那么您可能正在寻找List<T>。无论如何,如果用例足够复杂,我会实施 my 锁定策略。

  

当我收到具有唯一groupId的第一招请求时,我将创建一个   列表,然后将此请求添加到该列表中,然后开始处理   列表,如果我收到另一个具有相同groupId的请求,则必须添加到同一列表中

我认为您最好使用带有CopyOnWriteArrayList块的自定义锁定策略。

答案 1 :(得分:0)

我怀疑List是否适合您的用例。由于您是在线程之间传递数据,因此BlockingQueue似乎更加自然。

作为示例,以下是基于以下假设的实现:

  • 有1个box生产者,即:

    1)生成box,其中groupId的随机范围为1到3

    2)将box放入 lane

  • 有3个box消费者,每个消费者:

    1)从box收到lane

    2)如果消费者的groupId与盒子groupId匹配,则消耗该盒子

  • 不使用其他框架(仅核心Java)

import java.util.*;
import java.util.concurrent.*;

class Answer {
  public static void main(String[] args) {
     LinkedBlockingQueue<Box> lane = new LinkedBlockingQueue<>();

     Producer p = new Producer(lane);
     Consumer c1 = new Consumer(1, lane);
     Consumer c2 = new Consumer(2, lane);
     Consumer c3 = new Consumer(3, lane);

     new Thread(p).start();
     new Thread(c1).start();
     new Thread(c2).start();
     new Thread(c3).start();
  }
}

class Producer implements Runnable {
   private final LinkedBlockingQueue<Box> lane;
   Producer(LinkedBlockingQueue<Box> lane) { 
     this.lane = lane;
   }
   public void run() {
     try {
       while (true) { 
         lane.put(new Box(produceGroupId())); 
       }
     } catch (InterruptedException ex) {
       Thread.currentThread().interrupt();  // set interrupt flag
     }
   }
   int produceGroupId() {
     // generate random int between 1 and 3
     return ThreadLocalRandom.current().nextInt(1, 4);
   }
}

class Consumer implements Runnable {
   private final int groupId;
   private final BlockingQueue<Box> lane;
   Consumer(int groupId, BlockingQueue<Box> lane) { 
     this.groupId = groupId;
     this.lane = lane;
   }
   public void run() {
     while (true) {
       Box box = lane.peek();
       if (box != null && box.getGroupId() == this.groupId) {
         consume(lane.poll()); 
       }
     }
   }
   void consume(Box box) { 
     System.out.println("Consumer " + groupId + " received " + box + " for proxessing.");
   }
}

class Box {
  private final int groupId;
  public Box(int groupId) {
    this.groupId = groupId;
  }

  public int getGroupId() {
    return this.groupId;
  }

  @Override
  public String toString() {
    return "<Box " + groupId + ">";
  }
}

如果目标是拥有 3条单独的车道,则实施会有所不同:

import java.util.*;
import java.util.concurrent.*;

class Answer {
  public static void main(String[] args) {
     BlockingQueue<Box> lane1 = new LinkedBlockingQueue<Box>();
     BlockingQueue<Box> lane2 = new LinkedBlockingQueue<Box>();
     BlockingQueue<Box> lane3 = new LinkedBlockingQueue<Box>();
     Map<Integer, BlockingQueue<Box>> lanes = new ConcurrentHashMap<Integer, BlockingQueue<Box>>();
     lanes.put(1, lane1);
     lanes.put(2, lane2);
     lanes.put(3, lane3);

     Producer p = new Producer(lanes);
     Consumer c1 = new Consumer(1, lane1);
     Consumer c2 = new Consumer(2, lane2);
     Consumer c3 = new Consumer(3, lane3);

     new Thread(p).start();
     new Thread(c1).start();
     new Thread(c2).start();
     new Thread(c3).start();
  }
}

class Producer implements Runnable {
   private final Map<Integer, BlockingQueue<Box>> lanes;
   Producer(Map<Integer, BlockingQueue<Box>> lanes) { 
     this.lanes = lanes;
   }
   public void run() {
     try {
       while (true) { 
         int groupId = produceGroupId();
         BlockingQueue<Box> lane = lanes.get(groupId);
         lane.put(new Box(groupId)); 
       }
     } catch (InterruptedException ex) {
       Thread.currentThread().interrupt();
     }
   }
   int produceGroupId() {
     // generate random int between 1 and 3
     return ThreadLocalRandom.current().nextInt(1, 4);
   }
}

class Consumer implements Runnable {
   private final int consumerId;
   private final BlockingQueue<Box> lane;
   Consumer(int consumerId, BlockingQueue<Box> lane) { 
     this.consumerId = consumerId;
     this.lane = lane;
   }
   public void run() {
     try {
       while (true) {
         consume(lane.take()); 
       }
     } catch (InterruptedException ex) {}
   }
   void consume(Box box) { 
     System.out.println("Consumer " + consumerId + " received " + box + " for proxessing.");
   }
}

class Box {
  private final int groupId;
  public Box(int groupId) {
    this.groupId = groupId;
  }

  public int getGroupId() {
    return this.groupId;
  }

  @Override
  public String toString() {
    return "<Box " + groupId + ">";
  }
}