锁定免费解决方案,同时从映射中增加计数器,然后读取它



我正在尝试测量客户端代码的性能。这意味着end to end client side code占用了多少时间,客户端代码中的其他类很少。所以我做了基准测试。

下面是我目前正在使用的简单程序。但是有一个问题。

public class PerformanceTest {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(5);
        try {
            for (int i = 0; i < 10 * 5; i++) {
                executor.submit(new ThreadTask(i));
            }
            executor.shutdown();
            executor.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
        } catch (InterruptedException e) {
        }
    }
}
下面是实现Runnable interface的类
class ThreadTask implements Runnable {
    private int id;
    public static ConcurrentHashMap<Long, AtomicLong> millisecondsMap = new ConcurrentHashMap<Long, AtomicLong>();

    public ThreadTask(int id) {
        this.id = id;
    }
    @Override
    public void run() {

        long start = System.nanoTime();
        attributes = beClient.getAttributes(columnsList);
        long end = System.nanoTime() - start;
        final AtomicLong before = millisecondsMap.putIfAbsent(end / 1000000L, new AtomicLong(1L));
        if (before != null) {
            before.incrementAndGet(); //this is a blocking call in IBM JVM
        }
    }
}

问题陈述:-

我在我的机器上运行IBM JVM。因为我在一家公司工作,他们使用IBM JVM而不是SUN JVM,所以我不能改变JVM部分。

所以在IBM JVM中incrementAndGet()方法的样子,首先对我来说很奇怪

/**
 * Atomically increments by one the current value.
 *
 * @return the updated value
 */
public final synchronized long incrementAndGet() {                          //IBM-perf_AtomicLong
   ++value;                                                                 //IBM-perf_AtomicLong
   return value;                                                            //IBM-perf_AtomicLong
}

所以这是一个阻塞调用,因为它是synchronized,这意味着每个线程将彼此等待。现在我正在寻找Lock free solution来衡量每种方法的性能。

我知道,这里会有微小的延迟。但是,无论我想在客户端代码中测量什么方法的性能,我通常都将下面一行放在方法

的上方。

long start = System.nanoTime();

方法相同但ConcurrentHashMap

后面这两行
long end = System.nanoTime() - start;
final AtomicLong before = millisecondsMap.putIfAbsent(end / 1000000L, new AtomicLong(1L));
        if (before != null) {
            before.incrementAndGet();// this is a blocking call in IBM JVM
        }

所以如果我在客户端代码的不同类中围绕5-8 different methods有相同的上面代码。然后端到端性能测量将是错误的,因为每个线程将在那里等待增加值。因此,这就是我正在寻找无锁解决方案的原因。

有什么简单的方法吗?有人能举个例子吗?

提前感谢。

更新代码:

public static ConcurrentHashMap<Long, Long> millisecondsMap = new ConcurrentHashMap<Long, Long>();
@Override
public void run() {

    long start = System.nanoTime();
    beAttributes = client.getAttributes(columnsList);
    long end = System.nanoTime() - start;
    long key = end / 1000000L;
    boolean done = false;
    while(!done) {
        long oldValue = millisecondsMap.get(key);
        done = millisecondsMap.replace(key, oldValue, oldValue + 1);
    }
}

这个代码也是线程安全代码吗?因为它将被多个线程访问。

与其使用AtomicLong,不如使用ConcurrentHashMap的replace(key, old value, new value)方法来增加该值

ConcurrentHashMap<Long, Long> millisecondsMap = new ConcurrentHashMap<>();
long key = end / 1000000L;
boolean done = false;
while(!done) {
    Long oldValue = millisecondsMap.putIfAbsent(key, 1L);
    if(oldValue != null) {
        done = millisecondsMap.replace(key, oldValue, oldValue + 1);
    } else {
        done = true;
    }
}

相关内容

  • 没有找到相关文章

最新更新