Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/381.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 无锁解决方案,同时从映射中递增计数器,然后读取它_Java_Multithreading_Concurrency_Atomicity_Ibm Jvm - Fatal编程技术网

Java 无锁解决方案,同时从映射中递增计数器,然后读取它

Java 无锁解决方案,同时从映射中递增计数器,然后读取它,java,multithreading,concurrency,atomicity,ibm-jvm,Java,Multithreading,Concurrency,Atomicity,Ibm Jvm,我试图衡量客户端代码的性能。这意味着客户端代码需要多少时间端到端的代码以及客户端代码中很少有其他类。因此,我围绕这一点进行了基准测试 下面是我目前正在使用的简单程序。但这有一个问题 public class PerformanceTest { public static void main(String[] args) { ExecutorService executor = Executors.newFixedThreadPool(5); try

我试图衡量客户端代码的性能。这意味着客户端代码需要多少时间
端到端的代码
以及客户端代码中很少有其他类。因此,我围绕这一点进行了基准测试

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

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) {

        }
    }
}
问题陈述:-

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

}
我正在我的机器上运行
ibmjvm
。由于我在一家公司工作,他们使用
ibmjvm
而不是
sunjvm
,因此我无法更改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
}
因此,它是一个阻塞调用,因为它是同步的,这意味着每个线程都在等待对方。现在我正在寻找
无锁解决方案
来衡量每种方法的性能

我知道,这里会有很小的延迟。但是,无论我想在客户端代码中度量什么方法的性能,我通常都会在该方法的上方加上一行

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个不同的方法
。然后,端到端性能度量将是错误的,因为每个线程都将在那里等待增加值。因此,这就是为什么我正在寻找这个无锁解决方案

有什么简单的方法可以做到这一点吗?有人能举个例子吗

提前谢谢

更新代码:-

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

}
公共静态ConcurrentHashMap毫秒映射=新ConcurrentHashMap(); @凌驾 公开募捐{ 长启动=System.nanoTime(); BeatAttributes=client.getAttributes(columnsList); long end=System.nanoTime()-开始; 长键=结束/100000ml; 布尔完成=假; 而(!完成){ long oldValue=毫秒映射获取(键); 完成=毫秒映射替换(键,旧值,旧值+1); } }

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

使用ConcurrentHashMap的
替换(键、旧值、新值)
方法来增加值,而不是使用原子长度

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;
    }
}
ConcurrentHashMap毫秒map=new ConcurrentHashMap();
长键=结束/100000ml;
布尔完成=假;
而(!完成){
长oldValue=毫秒映射putIfAbsent(键,1L);
if(oldValue!=null){
完成=毫秒映射替换(键,旧值,旧值+1);
}否则{
完成=正确;
}
}

使用ConcurrentHashMap的
替换(键、旧值、新值)
方法来增加值,而不是使用原子长度

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;
    }
}
ConcurrentHashMap毫秒map=new ConcurrentHashMap();
长键=结束/100000ml;
布尔完成=假;
而(!完成){
长oldValue=毫秒映射putIfAbsent(键,1L);
if(oldValue!=null){
完成=毫秒映射替换(键,旧值,旧值+1);
}否则{
完成=正确;
}
}


IBM jdk源代码是否可以在某处进行检查?我有个主意。我想我没有带源代码。eclipse中唯一显示的类文件。这个类文件在
rt.jar
@TechGeeky中,我很好奇:你为什么要放弃
FutureTask
策略?太乱了?@acdcjunior,在这一点上你可以学到一些好东西。但我在想,与FutureTask one相比,可能还有其他更简单的方法来实现同样的目标。如果我没有发布这个问题,我就不知道我们也可以通过其他方式解决同样的问题,这也会做同样的事情。但是,我将再次在这两个选项上运行一些基准测试,并将检查每个选项的行为。是否可以在某处检查IBM jdk源代码?我有个主意。我想我没有带源代码。eclipse中唯一显示的类文件。这个类文件在
rt.jar
@TechGeeky中,我很好奇:你为什么要放弃
FutureTask
策略?太乱了?@acdcjunior,在这一点上你可以学到一些好东西。但我在想,与FutureTask one相比,可能还有其他更简单的方法来实现同样的目标。如果我没有发布这个问题,我就不知道我们也可以通过其他方式解决同样的问题,这也会做同样的事情。不过,我将再次对这两个选项运行一些基准测试,并将检查每个选项的行为,以获得建议。你能给我举个例子吗?这样,对我来说就更有意义了。谢谢你的帮助。请参阅我的编辑<如果在分配和
replace
调用之间更改了
oldValue
,则code>replace
将返回false,并将地图的值保持不变;如果
oldValue
匹配与键关联的地图的当前值,并将值替换为
oldValue+1
,则返回true。感谢Zim Zam,我刚刚用示例代码更新了我的问题。我只是想确定一下,我是否把一切都做好了。你能看一看并告诉我它对你是否合适吗?还有一件事,这个代码是线程安全代码吗?因为它将被多个线程访问。顺便说一下:这是Sun的
AtomicLong
incrementAndGet()
上执行的相同策略(一种算法)。我觉得你的代码不错。是的,这是线程安全的,就像acdcjunior评论的那样,这是一种比较和交换算法,在许多无锁实现中非常常见。例如,请参见C#类的CompareExchange方法,这些方法可以做同样的事情。感谢Zim Zam的建议。你能给我举个例子吗?这样,对我来说就更有意义了。谢谢你