yeg*_*256 3 java multithreading thread-safety
这个类是线程安全的吗?
class Counter {
private ConcurrentMap<String, AtomicLong> map =
new ConcurrentHashMap<String, AtomicLong>();
public long add(String name) {
if (this.map.get(name) == null) {
this.map.putIfAbsent(name, new AtomicLong());
}
return this.map.get(name).incrementAndGet();
}
}
Run Code Online (Sandbox Code Playgroud)
你怎么看?
是的,只要你让地图最终完成.if是没有必要的,但如果你愿意,你可以出于性能原因保留它,尽管它很可能没有明显的区别:
public long add(String name) {
this.map.putIfAbsent(name, new AtomicLong());
return this.map.get(name).incrementAndGet();
}
Run Code Online (Sandbox Code Playgroud)
编辑
为此,我已经快速测试了两种实现(有和没有检查).对同一个字符串进行10百万次调用:
这证实了我所说的内容:除非你将这种方法称为数百万次,或者它是代码性能的关键部分,否则它没有任何区别.
编辑2
完整的测试结果 - 看哪BetterCounter会产生更好的结果.现在测试非常具体(没有争用+ get始终有效)并且不一定与您的用法相对应.
计数器:482 ms
LazyCounter:207 ms
MPCounter:303 ms
BetterCounter:135 ms
public class Test {
public static void main(String args[]) throws IOException {
Counter count = new Counter();
LazyCounter lazyCount = new LazyCounter();
MPCounter mpCount = new MPCounter();
BetterCounter betterCount = new BetterCounter();
//WARM UP
for (int i = 0; i < 10_000_000; i++) {
count.add("abc");
lazyCount.add("abc");
mpCount.add("abc");
betterCount.add("abc");
}
//TEST
long start = System.nanoTime();
for (int i = 0; i < 10_000_000; i++) {
count.add("abc");
}
long end = System.nanoTime();
System.out.println((end - start) / 1000000);
start = System.nanoTime();
for (int i = 0; i < 10_000_000; i++) {
lazyCount.add("abc");
}
end = System.nanoTime();
System.out.println((end - start) / 1000000);
start = System.nanoTime();
for (int i = 0; i < 10_000_000; i++) {
mpCount.add("abc");
}
end = System.nanoTime();
System.out.println((end - start) / 1000000);
start = System.nanoTime();
for (int i = 0; i < 10_000_000; i++) {
betterCount.add("abc");
}
end = System.nanoTime();
System.out.println((end - start) / 1000000);
}
static class Counter {
private final ConcurrentMap<String, AtomicLong> map =
new ConcurrentHashMap<String, AtomicLong>();
public long add(String name) {
this.map.putIfAbsent(name, new AtomicLong());
return this.map.get(name).incrementAndGet();
}
}
static class LazyCounter {
private final ConcurrentMap<String, AtomicLong> map =
new ConcurrentHashMap<String, AtomicLong>();
public long add(String name) {
if (this.map.get(name) == null) {
this.map.putIfAbsent(name, new AtomicLong());
}
return this.map.get(name).incrementAndGet();
}
}
static class BetterCounter {
private final ConcurrentMap<String, AtomicLong> map =
new ConcurrentHashMap<String, AtomicLong>();
public long add(String name) {
AtomicLong counter = this.map.get(name);
if (counter != null)
return counter.incrementAndGet();
AtomicLong newCounter = new AtomicLong();
counter = this.map.putIfAbsent(name, newCounter);
return (counter == null ? newCounter.incrementAndGet() : counter.incrementAndGet());
}
}
static class MPCounter {
private final ConcurrentMap<String, AtomicLong> map =
new ConcurrentHashMap<String, AtomicLong>();
public long add(String name) {
final AtomicLong newVal = new AtomicLong(),
prevVal = map.putIfAbsent(name, newVal);
return (prevVal != null ? prevVal : newVal).incrementAndGet();
}
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
314 次 |
| 最近记录: |