2

我正在开发的应用程序有问题。
我有两个线程,Prod 和 Cons,它们分别写入和读取共享的Queue. 这里都很标准。
此应用程序的目标是让 Prod 读取文件并将每一行添加到Queue.Cons 必须读取这些行并成对“匹配”它们(遵循一些标准)。

问题是,为了让 Cons 发挥作用,它必须从 中“处理”几行, Queue并且只删除那些形成 Pair 的行。例如,如果以下是QueueProd 填写的 Q:

Q:
-
A1  
A2  
B1  
C1  
D1  
C2  
D2    
B2  
E1  
E2

缺点应该创建 Pairs (A1,A2),(B1,B2),(C1,C2) 等...(对的顺序是要求)。

我的问题是,要创建 Pair (B1,B2),Cons 需要首先分析 C1、D1、D2 和 C2 并发现它们与 B1 不匹配;然后找到 B2 并且 B1 和 B2 都必须从 Q 中删除,而不修改先前不匹配元素(C1、D1 等)的顺序。
目前,我通过 Cons 解决了始终从队列中删除第一个元素,如果不匹配,则将其保存在 Cons 的另一个内部队列中;当找到匹配的元素时,会创建 Pair 并将保存在内部队列中的所有元素“重新注入”到 Q 的头部(实际上是 a DeQue)。

虽然这种方法适用于简单的情况,但它存在无可救药的缺陷。鉴于 Prod 一直在运行,很可能会发生这样的情况,当 Cons 删除不匹配的元素时,Prod 会添加新行,当 Cons 尝试在 Q 上重新插入消息时有效地产生死锁。

我还认为 Cons 只能“窥视” Q 中的元素并仅删除匹配的元素,但这意味着访问Deque.

有人对这个问题有建议吗?我总是可以“创建”一个Deque可以满足我需要的东西,但我真的不喜欢!太容易出错了...

谢谢!

4

2 回答 2

1

根据匹配的执行方式(例如,如果给定“C1”,您知道匹配必须是“C2”而不是“C146”或其他),将 Queue 替换为带有“C1”的LinkedHashMap可能是有意义的" 和 "C2" 等作为键。生产者将元素添加到LinkedBlockingQueue(没有最大容量),而消费者轮询队列并使用ContainsKey在 hashmap 上确定匹配元素是否已经在 map 中;如果匹配,则从地图中删除匹配元素,否则将当前元素添加到地图中。当消费者处理完所有生产者数据后,LinkedHashMap 将拥有所有不匹配元素的有序列表。只需确保您能够将“C2”匹配到“C1”以及能够将“C1”匹配到“C2”

public class SharedCollections {
    public static LinkedBlockingQueue<Object> workList = new LinkedBlockingQueue<>();
}

public class Producer implements Runnable {
    public void run() {
        while(true) {
            SharedCollections.workList.offer(obj);
        }
    }
}

public class Consumer implements Runnable {
    LinkedHashMap<String, Object> hashMap = new LinkedHashMap<>();
    public void run() {
        while(true) {
            Object obj = SharedCollections.workList.take(); // blocks if the workList is empty
            String matchingId = getMatchingId(obj.id); // e.g. returns "C2" if the object's id is "C1"
            if(hashMap.containsKey(matchingId)) {
                hashMap.remove(matchingId);
            } else {
                hashMap.put(obj.id, obj);
            }
        }
    }
}
于 2013-04-25T13:48:14.677 回答
1

如果您可以通过仅查看单个行将行拆分为多个类别(或存储桶)(即每种行类型确实具有不同的格式),您可以继续使用 BlockingQueue 来连接生产者和消费者。

对于消费者从队列中读取的每一行,它确定该行的正确存储桶,并使用 Linked(Hash)Map 到

  • 存储它,如果没有行已经存储在桶中
  • 产生一对已经存储在地图中的线并发出它

队列耗尽后,消费者将产生所有遇到的对,并且消费者的 LinkedMap 按插入顺序保存所有未配对的行。

这将把匹配封装在消费者内部,保持生产者、消费者和连接它们的队列之间的关注点清晰分离。

于 2013-04-25T15:19:26.367 回答