多线程中的共享锁-Java

多线程中的共享锁-Java,java,multithreading,Java,Multithreading,我是多线程新手,因此如果有人建议我是否做了正确的事情,我将不胜感激 我需要做以下工作: 预处理传入消息并将其按入>以进行随机访问。对该消息状态的任何进一步请求都将发送UUID,然后可以从映射中检索UUID进行随机访问 同时,我需要另一个线程,它将按插入顺序依次访问值(或消息),并处理它们 下面是在类存储中操作映射的第一点 public class Store { static ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

我是多线程新手,因此如果有人建议我是否做了正确的事情,我将不胜感激

我需要做以下工作:

预处理传入消息并将其按入>以进行随机访问。对该消息状态的任何进一步请求都将发送UUID,然后可以从映射中检索UUID进行随机访问

同时,我需要另一个线程,它将按插入顺序依次访问值(或消息),并处理它们

下面是在类存储中操作映射的第一点

public class Store {

static ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
static Map<String, MessageFileRead> fileGeneratorMap = Collections.synchronizedMap(new LinkedHashMap());


public static boolean insertRecord(MessageFileRead messageFileRead) {
    boolean processed = false;
    lock.writeLock().lock();
    try {

        if (!fileGeneratorMap.containsKey(messageFileRead.uuid)) {
            fileGeneratorMap.put(messageFileRead.uuid, messageFileRead);
            processed = true;
        }
    } finally {
        lock.writeLock().unlock();
    }
    return processed;
}

public static boolean updateRecord(String uuid, Status status) {
    boolean processed = false;
    lock.writeLock().lock();
    try {
        if (fileGeneratorMap.containsKey(uuid)) {
            fileGeneratorMap.get(uuid).status = status;
            processed = true;
        }
    } finally {
        lock.writeLock().unlock();
    }
    return processed;
}

public static boolean deleteRecord(String uuid) {
    boolean processed = false;
    lock.writeLock().lock();
    try {
        for (final Iterator<Map.Entry<String, MessageFileRead>> it = fileGeneratorMap.entrySet().iterator(); it.hasNext(); ) {
            Map.Entry<String, MessageFileRead> entry = it.next();
            if (entry.getKey().equals(uuid)) {
                it.remove();
                break;
            }
        }
    } finally {
        lock.writeLock().unlock();
    }
    return processed;
}
公共类存储{
静态ReentrantReadWriteLock锁=新的ReentrantReadWriteLock();
静态映射fileGeneratorMap=Collections.synchronizedMap(新LinkedHashMap());
公共静态布尔插入记录(MessageFileRead MessageFileRead){
布尔值=假;
lock.writeLock().lock();
试一试{
如果(!fileGeneratorMap.containsKey(messageFileRead.uuid)){
fileGeneratorMap.put(messageFileRead.uuid,messageFileRead);
已处理=真;
}
}最后{
lock.writeLock().unlock();
}
已处理退货;
}
公共静态布尔更新记录(字符串uuid,状态){
布尔值=假;
lock.writeLock().lock();
试一试{
if(fileGeneratorMap.containsKey(uuid)){
fileGeneratorMap.get(uuid).status=status;
已处理=真;
}
}最后{
lock.writeLock().unlock();
}
已处理退货;
}
公共静态布尔删除记录(字符串uuid){
布尔值=假;
lock.writeLock().lock();
试一试{
for(final Iterator it=fileGeneratorMap.entrySet().Iterator();it.hasNext();){
Map.Entry=it.next();
if(entry.getKey().equals(uuid)){
it.remove();
打破
}
}
}最后{
lock.writeLock().unlock();
}
已处理退货;
}
这是使用迭代器顺序访问映射的代码,迭代器位于同一个包中另一个类的另一个线程中。这在一个方法中,该方法是调用新工作线程的框架代码的一部分

    while (!stopped) {
        try {
            Store.lock.writeLock().lock();
            for (final Iterator<Map.Entry<String, MessageFileRead>> it = Store.fileGeneratorMap.entrySet().iterator(); it.hasNext(); ) {
                Map.Entry<String, MessageFileRead> entry = it.next();
                MessageRead message = entry.getValue();

                if (message.status != COMPLETED) {
                    JSONObject response = DbService.process(message);
                    // And the above process method internally calls the updateRecord with a status of COMPLETED so that this message is marked as COMPLETED processing and is not picked up in the next run.
                }
            }
        } finally {
            Store.lock.writeLock().unlock();
        }
    }
while(!stopped){
试一试{
Store.lock.writeLock().lock();
for(final Iterator it=Store.fileGeneratorMap.entrySet().Iterator();it.hasNext();){
Map.Entry=it.next();
MessageRead message=entry.getValue();
如果(message.status!=已完成){
JSONObject响应=DbService.process(消息);
//上面的process方法在内部调用状态为COMPLETED的updateRecord,以便将此消息标记为COMPLETED processing,并且在下一次运行中不会拾取该消息。
}
}
}最后{
Store.lock.writeLock().unlock();
}
}

到目前为止,我还没有遇到任何问题,但仍处于初始阶段,我想知道我是否做了正确的事情,因此欢迎提供任何建议。

在ConcurrentHashMap可用时,我会质疑Collections.synchronizedMap的使用,您可以避免显式锁定映射


代码看起来不错。不过,如果您没有预见到需要只读访问,可以使用synchronized(lock){…}而不是writeLock来简化它。示例:

public static boolean deleteRecord(String uuid) {
    boolean processed = false;
    synchronized(lock) {
        for (final Iterator<Map.Entry<String, MessageFileRead>> it = fileGeneratorMap.entrySet().iterator(); it.hasNext(); ) {
            Map.Entry<String, MessageFileRead> entry = it.next();
            if (entry.getKey().equals(uuid)) {
                it.remove();
                break;
            }
        }
    } 
    return processed;
}
公共静态布尔删除记录(字符串uuid){
布尔值=假;
已同步(锁定){
for(final Iterator it=fileGeneratorMap.entrySet().Iterator();it.hasNext();){
Map.Entry=it.next();
if(entry.getKey().equals(uuid)){
it.remove();
打破
}
}
} 
已处理退货;
}

您的
deleteRecord
代码不需要使用迭代键来删除。如果您只是想查看,我建议迁移到codereview.stackexchange.com如果您只是在阅读,那么您应该在顺序访问过程中使用
readLock
。它们可以很好地使用
writeLock
-请参阅。谢谢Chris,对不起,我太天真了。但这是不是意味着我只是复制粘贴它一次,还是有其他方法可以做到这一点?您可以使用fileGeneratorMap.remove(键)不要反复寻找正确的密钥然后删除。如果你使用的是
锁,你应该始终如一地这样做。在你发布的代码中,你似乎是这样做的。因此,没有必要使用
同步地图
,也不应该使用它,因为这是一种伪装。读者看到类似
同步的东西…
不会寻找保护
。除此之外,这些
布尔处理的
局部变量都是无意义的。在
返回
语句的位置,它们不可能是
,因此它们暗示了对程序流的根本误解…谢谢Vijay,我在哪里读到了至少,它不会给我对添加的元素的顺序访问权。我还需要按照插入它们的顺序检索它们。因此,这种方法。是的,ConcurrentHashMap不会给你顺序访问权。