Java 线程安全访问计数器

Java 线程安全访问计数器,java,multithreading,Java,Multithreading,我正在尝试实现线程安全访问计数器。我需要做的是创建一个包含路径和整数计数器的HashMap。它有两种方法,用于检查映射是否包含路径,并在路径出现时相应地增加计数,如下所示 public class AccessCounter { private HashMap<Integer,java.nio.file.Path> counter= new HashMap<Integer,java.nio.file.Path>(); private ReentrantLock lock

我正在尝试实现线程安全访问计数器。我需要做的是创建一个包含路径和整数计数器的HashMap。它有两种方法,用于检查映射是否包含路径,并在路径出现时相应地增加计数,如下所示

public class AccessCounter {
private HashMap<Integer,java.nio.file.Path> counter= new HashMap<Integer,java.nio.file.Path>();
private ReentrantLock lock = new ReentrantLock();  
private Path path ;
private RequestHandler rq; 

public void map(HashMap<Integer,java.nio.file.Path> counter){ 
    counter.put(10,Paths.get("/Users/a.html"));
    counter.put(5, Paths.get("b.html")); 
    counter.put(2, Paths.get("c.txt"));
    counter.put(7, Paths.get("d.txt")); 
}

public void increment(){ 
    lock.lock(); 
    System.out.println("Lock Obtained");
    try{ 
        if(counter.keySet().equals(rq.fileName())){
            for(Integer key: counter.keySet()){
                Path text = counter.get(key);   
                key++;
            }
        }
        else { 
            counter.put(1,path);
        }
    }finally{
        lock.unlock();
        System.out.println("Lock released");
    }
}

public void getCount(){ 
    lock.lock(); 
    System.out.println("Lock Obtained");
    try{ 
        if(counter.keySet().equals(rq.fileName())){
            for(Integer key: counter.keySet()){
                Path text = counter.get(key);   
                key++;
            }
        }
        else { 
            return ;
        }
    }finally{
        lock.unlock();
        System.out.println("Lock released");
    }
}
}

私有HashMap计数器=新建 哈希图

您需要的不是HashMap,而是HashMap,因为您的目的是计算具有相同路径的条目数

我看到了一个很好的优化,除非您想尝试使用普通HashMap并在用户代码中锁定:

您可以使用ConcurrentHashMap代替上面的HashMap

ConcurrentHashMap有一个putIfAbsent。。。方法,该方法在单个语句中以原子方式执行它

AtomicInteger允许我们使用incrementAndGet方法以原子方式递增

在用户代码中都没有额外的锁/同步

私有HashMap计数器=新建 哈希图

您需要的不是HashMap,而是HashMap,因为您的目的是计算具有相同路径的条目数

我看到了一个很好的优化,除非您想尝试使用普通HashMap并在用户代码中锁定:

您可以使用ConcurrentHashMap代替上面的HashMap

ConcurrentHashMap有一个putIfAbsent。。。方法,该方法在单个语句中以原子方式执行它

AtomicInteger允许我们使用incrementAndGet方法以原子方式递增


这两种方法在用户代码中都没有额外的锁/同步。

使用ConcurrentHashMap和AtomicLong是线程安全性和简单性所需要的

final ConcurrentMap<Path, AtomicLong> counterMap = new ConcurrentHashMap<>();

public void incrementFor(Path path) {
    counterMap.computeIfAbsent(path, p -> new AtomicLong()).incrementAndGet();
}

public long getCount(Path path) {
    AtomicLong l = counterMap.get(path);
    return l == null ? 0 : l.get();
}
ComputeFabSent将以线程安全的方式根据需要放置一个新的原子


注意:由于ConcurrentMap支持并发访问,您可以让多个线程同时使用此映射,前提是它们使用ConcurrentHashMap和AtomicLong访问不同的路径,这是线程安全性和简单性所需要的

final ConcurrentMap<Path, AtomicLong> counterMap = new ConcurrentHashMap<>();

public void incrementFor(Path path) {
    counterMap.computeIfAbsent(path, p -> new AtomicLong()).incrementAndGet();
}

public long getCount(Path path) {
    AtomicLong l = counterMap.get(path);
    return l == null ? 0 : l.get();
}
ComputeFabSent将以线程安全的方式根据需要放置一个新的原子


注意:由于ConcurrentMap支持并发访问,您可以让多个线程同时使用此映射,前提是它们正在访问不同的路径

我想您希望映射为HashMap,而不是HashMap,因为您希望计算具有相同路径的条目数。是吗?是的,这正是我需要做的。我会解决的。感谢您提供的类似信息,以及您不想使用ConcurrentHashMap的原因。这有一个putIfAbsent方法,它以原子方式执行,而AtomicInteger可以使用incrementAndGet方法以原子方式递增,而不需要在用户代码中进行任何锁定/同步。我认为您希望映射为HashMap而不是HashMap,因为您希望拥有具有相同路径的条目的计数。是吗?是的,这正是我需要做的。我会解决的。感谢您提供的类似信息,以及您不想使用ConcurrentHashMap的原因。这有一个putIfAbsent方法,它以原子方式执行,AtomicInteger可以使用incrementAndGet方法以原子方式递增,而用户代码中没有任何锁定/同步。感谢您的建议!肯定会有所改变。目前,您是否看到代码中有任何错误,因为我无法运行it@Azib.H我认为需要做一些改变。RequestHandler中的ac未初始化。您需要确保两个线程使用相同的ac,否则每个ac都有自己的HashMap。我看不出你在哪里叫地图。。。方法交流。即使在选择。。。方法创建三个文件实例,但不在任何地方使用。最后,用最新的代码更新您的问题。谢谢您的建议!肯定会有所改变。目前,您是否看到代码中有任何错误,因为我无法运行it@Azib.H我认为需要做一些改变。RequestHandler中的ac未初始化。您需要确保两个线程使用相同的ac,否则每个ac都有自己的HashMap。我看不出你在哪里叫地图。。。方法交流。即使在选择。。。方法创建三个文件实例,但不在任何地方使用。最后,用最新的代码更新你的问题。这看起来更简单更好+谢谢各位!这看起来更简单更好+谢谢各位!真的很有帮助