有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!


共 (1) 个答案

  1. # 1 楼答案

    如果您的方法需要时间,并且只想在ID相同(或任何参数组合)时阻止并发访问,则需要为每个ID(或任何参数组合)存储锁

    这些锁可以存储在Map

    如果它只是一个类型为Long的ID,那么可以直接将其用作映射的键。如果有多个参数,请将它们与所需的equals/hashcode方法一起包装到自定义类中

    private Map<Long, Lock> locks = new ConcurrentHashMap<>(100);
    
    private void startProcess(Long id) {
        Lock lock = locks.computeIfAbsent(id, id2 -> new ReentrantLock());
    
        lock.lock();
        try {
            System.out.println(System.currentTimeMillis() + " Starting  " + id + " on thread " + Thread.currentThread().getName());
            try { Thread.sleep(2000); } catch (InterruptedException ex) { }
            System.out.println(System.currentTimeMillis() + " Done with " + id + " on thread " + Thread.currentThread().getName());
        } finally {
            lock.unlock();
            locks.remove(lock);
        }
    }
    

    致电:

    new Thread(() -> startProcess(1L), "A").start();
    new Thread(() -> startProcess(1L), "B").start();
    new Thread(() -> startProcess(2L), "C").start();
    

    这是一种可能的输出:

    1595950202869 Starting  1 on thread A
    1595950202879 Starting  2 on thread C
    1595950204870 Done with 1 on thread A
    1595950204870 Starting  1 on thread B
    1595950204879 Done with 2 on thread C
    1595950206870 Done with 1 on thread B
    

    [编辑]参数自定义类的示例代码:

    private Map<ProcessParams, Lock> locks = new ConcurrentHashMap<>(100);
    
    private void startProcess(long id, String name) {
        Lock lock = locks.computeIfAbsent(new ProcessParams(id, name), id2 -> new ReentrantLock());
    
        lock.lock();
        try {
            System.out.println(System.currentTimeMillis() + " Starting  " + name + " on thread " + Thread.currentThread().getName());
            try { Thread.sleep(2000); } catch (InterruptedException ex) { }
            System.out.println(System.currentTimeMillis() + " Done with " + name + " on thread " + Thread.currentThread().getName());
        } finally {
            lock.unlock();
            locks.remove(lock);
        }
    }
    
    public static class ProcessParams {
        private final long   id;
        private final String name;
    
        public ProcessParams(long id, String name) {
            this.id = id;
            this.name = Objects.requireNonNull(name, "name");
        }
    
        @Override
        public boolean equals(Object o) {
            if (this == o)
                return true;
    
            if (!(o instanceof ProcessParams))
                return false;
    
            ProcessParams other = (ProcessParams)o;
            return id == other.id && name.equals(other.name);
        }
    
        @Override
        public int hashCode() {
            int hashCode = 0x811C9DC5;
            hashCode = 0x01000193 * (hashCode ^ Long.hashCode(id));
            hashCode = 0x01000193 * (hashCode ^ name.hashCode());
            return hashCode;
        }
    }