我试图简单地在ConcurrentHashMap中打印所有键/值对.
我在网上找到了这个代码,我认为会这样做,但它似乎是获取有关桶/哈希码的信息.其实说实话输出很奇怪,可能我的程序不正确,但我首先要确保这部分是我想要使用的.
for (Entry<StringBuilder, Integer> entry : wordCountMap.entrySet()) {
String key = entry.getKey().toString();
Integer value = entry.getValue();
System.out.println("key, " + key + " value " + value);
}
Run Code Online (Sandbox Code Playgroud)
这为大约10个不同的键提供输出,其计数似乎是映射到插入的总插入数的总和.
我编写了一个计时器,用于衡量任何多线程应用程序中特定代码的性能.在下面的计时器中,它还将使用x毫秒的数量填充地图.我将使用这张地图作为我的直方图的一部分来进行进一步的分析,比如这几分钟的调用百分比等等.
public static class StopWatch {
public static ConcurrentHashMap<Long, Long> histogram = new ConcurrentHashMap<Long, Long>();
/**
* Creates an instance of the timer and starts it running.
*/
public static StopWatch getInstance() {
return new StopWatch();
}
private long m_end = -1;
private long m_interval = -1;
private final long m_start;
private StopWatch() {
m_start = m_interval = currentTime();
}
/**
* Returns in milliseconds the amount of time that has elapsed since the timer was created. If the
* …
Run Code Online (Sandbox Code Playgroud) 这可能是一个重复的问题,但我在一本关于并发的书中找到了这部分代码.这据说是线程安全的:
ConcurrentHashMap<String, Integer> counts = new ...;
private void countThing(String thing) {
while (true) {
Integer currentCount = counts.get(thing);
if (currentCount == null) {
if (counts.putIfAbsent(thing, 1) == null)
break;
} else if (counts.replace(thing, currentCount, currentCount + 1)) {
break;
}
}
}
Run Code Online (Sandbox Code Playgroud)
从我的(并发初学者)的角度来看,线程t1和线程t2都可以读取currentCount = 1
.然后两个线程都可以将地图的值更改为2.有人可以解释我代码是否正常?
java concurrency multithreading concurrenthashmap concurrent-programming
我正在测试ConcurrentHashMap
Oracle的Java 8实现:
ConcurrentMap<String, String> concurrentMap = new ConcurrentHashMap<>();
String result = concurrentMap.computeIfAbsent("A", k -> "B");
System.out.println(result); // "B"
result = concurrentMap.putIfAbsent("AA", "BB");
System.out.println(result); // null
Run Code Online (Sandbox Code Playgroud)
实施要求:
默认实现等效于此映射的以下步骤,然后返回当前值,如果现在不存在则返回null:
Run Code Online (Sandbox Code Playgroud)if (map.get(key) == null) { V newValue = mappingFunction.apply(key); if (newValue != null) return map.putIfAbsent(key, newValue); }
它表示然后返回当前值,如果现在不存在则返回null.那不应该回来null
吗?鉴于这putIfAbsent
也正在回归null
.
我在这里错过了什么?
我正在尝试找到这些答案,但无法在Google或Java文档中理解(或确认)它.
我的实现看起来像这样:
Map<String, POJO> map = new ConcurrentHashMap<String, POJO>();
Run Code Online (Sandbox Code Playgroud)
如果我做
value1 = map.get(key1);
value1.setProp(prop);
Run Code Online (Sandbox Code Playgroud)
任何其他线程可能会覆盖.
现在,我在想如果我喜欢以下内容:它会是一个原子操作/换句话说,它会阻止key1段吗?
map.compute(key1, (key1, value1) -> { value1.setProp(prop) });
Run Code Online (Sandbox Code Playgroud)
Javadoc的compute
功能
尝试计算指定键及其当前映射值的映射(如果没有当前映射,则为null).整个方法调用以原子方式执行.其他线程在此映射上的某些尝试更新操作可能在计算进行时被阻止,因此计算应该简短,并且不得尝试更新此Map的任何其他映射.
参考文献:
1. https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ConcurrentHashMap.html 2. https://docs.oracle.com/javase/8/docs/api/java /util/concurrent/ConcurrentHashMap.html#compute-K-java.util.function.BiFunction-
对于我的最终实现,我做了类似这样的事情,因为所有线程共享NewMap,最后,我新的POJO列表
抽象数据类型
public class NewMap {
private Map<String, POJO> map;
private boolean isUpdatable;
void NewMap(){
isUpdatable = true;
map = new ConcurrentHashMap();
}
void putPOJOProp1(String key, Type value) throws ReadOnlyException{
map.compute(key, (k,v) -> {
if(!isUpdatable) throw new ReadOnlyException();
if(k == null){
POJO p = new POJO(); …
Run Code Online (Sandbox Code Playgroud) 我今天遇到了一个非常意想不到的错误,虽然我能够找到一种方法来解决整个问题,但我不确定我是否完全理解它为什么会这样做.
我正在使用的代码最初是用JDK 7环境编写的,当然是针对JRE 7.在代码中我使用了一个ConcurrentHashMap
并且需要迭代地图中的键.为此,我使用的map.keySet()
是根据JavaDocs应该返回的Set<K>
.这很好用,直到我们的构建环境切换到JDK8.
当我们转移到JDK8时,我确保在调用javac时调用1.7的目标/源.当代码在想要遍历地图的键时开始失败时,我感到非常惊讶.没有抛出任何错误,没有异常,线程只是停止了.之后做一些研究,我发现Java8的实施ConcurrentHashMap
的.keySet()
方法返回一个KeySetView<K,V>
.
我通过使用开关解决了这一问题map.keySet()
,以得到一个Enumeration<K>
使用map.keys()
.
现在我对这个问题的猜测是,虽然项目是针对Java7编译的,因为使用了JDK8,Java8库被包含在内,但为什么在它出现不匹配时它没有抛出错误或异常?
正如这里所要求的是代码片段:
class MapProcessing
{
private ConcurrentHashMap<String, Object> map = new ConcurrentHashMap<String, Object>();
public MapProcessing()
{
map.put("First",new Object());
map.put("Second",new Object());
map.put("Third",new Object());
}
public void processing()
{
// when calling this type of loop causes a freeze on our system.
for(String key : map.keySet())
{
System.out.println(key);
}
}
public void working()
{
// This is what …
Run Code Online (Sandbox Code Playgroud) 今天我从一些JS课程中学到了什么是memoization并尝试用Java实现它.我有一个简单的递归函数来评估第n个Fibonacci数:
long fib(long n) {
if (n < 2) {
return n;
}
return fib(n - 1) + fib(n - 2);
}
Run Code Online (Sandbox Code Playgroud)
然后我决定使用HashMap来缓存递归方法的结果:
private static <I, O> Function<I, O> memoize(Function<I, O> fn) {
final Map<I, O> cache = new HashMap<>();
return in -> {
if (cache.get(in) != null) {
return cache.get(in);
} else {
O result = fn.apply(in);
cache.put(in, result);
return result;
}
};
}
Run Code Online (Sandbox Code Playgroud)
这按照我的预期工作,它允许我fib()
像这样记忆memoize(this::fib)
然后,我用Google搜索记忆化的Java中的主题,发现了一个问题:Java的记忆化方法,其中computeIfAbsent
提出比我的条件表达式短得多.
所以我期望工作的最终代码是:
public class FibMemo {
private …
Run Code Online (Sandbox Code Playgroud) 我正在计算电子选举的选票,并且在我的初始版本中我只有一个政党。每个选民将有不同的线程,线程将更新给定政党的选票计数。
我决定使用 ConcurrentHashMap,但结果不是我所期望的......
Map<String, Integer> voting = new ConcurrentHashMap<>();
for (int i = 0; i < 16; i++) {
new Thread(() -> {
voting.put("GERB", voting.getOrDefault("GERB", 0) + 1);
}).start();
}
for (int i = 0; i < 100; i++) {
voting.put("GERB", voting.getOrDefault("GERB", 0) + 1);
}
Thread.sleep(5000); // Waits for the threads to finish
for (String s : voting.keySet()) {
System.out.println(s + ": " + voting.get(s));
}
Run Code Online (Sandbox Code Playgroud)
结果每次都不一样——范围从 114 到 116。
ConcurrentHashMap 不应该同步吗?
使用remove()方法好吗?我读过一篇文章,说明同步还没有添加到remove方法中.如何从ConcurrentHashMap中正确删除特定项?
示例代码:
ConcurrentHashMap<String,Integer> storage = new ConcurrentHashMap<String,Integer>();
storage.put("First", 1);
storage.put("Second", 2);
storage.put("Third",3);
//Is this the proper way of removing a specific item from a tread-safe collection?
storage.remove("First");
for (Entry<String, Integer> entry : storage.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
// ...
System.out.println(key + " " + value);
}
Run Code Online (Sandbox Code Playgroud) 简介
假设我有一个ConcurrentHashMap单例:
public class RecordsMapSingleton {
private static final ConcurrentHashMap<String,Record> payments = new ConcurrentHashMap<>();
public static ConcurrentHashMap<String, Record> getInstance() {
return payments;
}
}
Run Code Online (Sandbox Code Playgroud)
然后我有来自不同来源的三个后续请求(全部由不同线程处理).
第一个服务发出请求,获取单例,创建Record
实例,生成唯一ID并将其放入Map
,然后将此ID发送到另一个服务.
然后第二个服务使用该ID发出另一个请求.它获取单例,查找Record
实例并修改它.
最后(可能在半小时后)第二个服务发出另一个请求,以便Record
进一步修改.
问题
在一些非常罕见的情况下,我遇到了 heisenbug.在日志中我可以看到,第一个请求成功放置Record
到Map
,第二个请求发现它的ID,并修改它,然后第三个请求,试图找到ID记录,但一无所获(get()
返回null
).
我发现有关ConcurrentHashMap
担保的一件事是:
在将对象放入任何并发集合之前的线程中的操作发生在从另一个线程中的集合访问或移除该元素之后的操作之前.
从这里开始.如果我做对了,它的字面意思是,它get()
可以返回实际上某个时间到Map的任何值,只要它不会破坏happens-before
不同线程中的动作之间的关系.
在我的情况下,它适用于这样:如果第三个请求不关心在处理第一个和第二个期间发生的事情,那么它可以null
从中读取Map
.
它不适合我,因为我真的需要从Map
最新的实际中得到Record
.
我尝试过什么
所以我开始思考,如何形成happens-before
后续Map
修改之间的关系; 并有想法.JLS 说(在17.4.4)认为: …