多线程中的共享锁 - Java

时间:2016-06-06 15:46:45

标签: java multithreading

我是多线程的新手,所以我很欣赏任何人对我是否做得对的建议。

我需要做以下事情:

预处理传入的消息并将其推送到<<数据结构。我使用了HashMap,其中消息的UUID作为密钥,消息本身作为值>>随机访问。对此消息状态的任何进一步请求都将发送到UUID,然后可以从Map中检索该随机访问。

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

所以,这是在类商店中操作Map的第一位

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;
}

这是使用Iterator顺序访问映射的代码,Iterator位于同一个包中另一个类的另一个线程中。这是一个方法,它是调用新工作线程的框架代码的一部分。

    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();
        }
    }

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

2 个答案:

答案 0 :(得分:0)

当ConcurrentHashMap可用时,我会质疑Collections.synchronizedMap的使用,你可以避免显式锁定地图。

https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ConcurrentHashMap.html

答案 1 :(得分:0)

代码看起来很好。但是,如果您没有预见到需要只读访问权限,则可以使用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;
}