[英]Java ConcurrentSkipListMap getting stuck in some threads
I have this container 我有这个容器
private ConcurrentMap<Integer,SortedMap<Long,Object>> users;
Which gets initialized in constructor users = new ConcurrentHashMap<>();
在构造函数中初始化的users = new ConcurrentHashMap<>();
and for each user it gets new ConcurrentSkipListMap<>()
并且为每个用户获取new ConcurrentSkipListMap<>()
I have this method which is called over and over again in threadpool 我有这种方法在线程池中被一遍又一遍地调用
private void process(Object obj){
// SOME CODE
SortedMap<Long,Object> q = users.get( obj.userId);
logger.debug("SECTION 1");
q.headMap( someNumber ).clear();
logger.debug("SECTION 2");
q.put( obj.someId, obj );
logger.debug("SECTION 3");
}
this method is called using executorService = Executors.newScheduledThreadPool(8);
使用executorService = Executors.newScheduledThreadPool(8);
调用此方法executorService = Executors.newScheduledThreadPool(8);
executorService.execute(new Runnable() {
@Override
public void run() {
process(obj);
}
});
sometimes it works fine but sometimes (I suppose on high load) for some user process methods (all calls) get stuck and never outputs SECTION 2 有时它可以正常工作,但有时(我想是在高负载下)对于某些用户处理方法(所有调用)会卡住并且从不输出第2节
and if I swap q.headMap( someNumber ).clear();
如果我交换q.headMap( someNumber ).clear();
and q.put( obj.someId, obj );
和q.put( obj.someId, obj );
it still doesn't output SECTION 2 它仍然不输出第2节
I also tried LinkedBlockingQueue
instead of ConcurrentSkipListMap
but I have same issue 我也尝试了LinkedBlockingQueue
而不是ConcurrentSkipListMap
但是我有同样的问题
it looks like a deadlock but I'm not using any synchronized statement on that structure. 它看起来像一个死锁,但我没有在该结构上使用任何同步语句。
please share your idea if you have one 如果有一个,请分享您的想法
There could multiple causes; 可能有多种原因; the most obvious one is unsynchronized code. 最明显的一个是不同步的代码。 Take thread-dumps to easily identify the cause. 进行线程转储以轻松找出原因。
Some issues: 一些问题:
In ConcurrentSkipListMap
JavaDocs it says at headMap()
: 在ConcurrentSkipListMap
JavaDocs中,它在headMap()
说:
The returned map will throw an IllegalArgumentException on an attempt to insert a key outside its range.
So if obj.someId.compareTo(someNumber) < 0
you can get an IllegalArgumentException
at put()
which is not treated anywhere. 因此,如果obj.someId.compareTo(someNumber) < 0
,则可以在put()
处获得IllegalArgumentException
,该obj.someId.compareTo(someNumber) < 0
在任何地方都不会得到处理。
Also this can lead to race conditions: 这也会导致比赛条件:
q.headMap( someNumber ).clear();
q.put( obj.someId, obj )
if two threads have (thread1) someNumber = (thread2) obj.someId
you get a race condition and who know what happens underneath. 如果两个线程具有(thread1) someNumber = (thread2) obj.someId
您会获得竞争条件,并且谁知道下面会发生什么。 Moreover, as JavaDocs say clear()
is not an atomical operation. 而且,正如JavaDocs所说, clear()
不是原子操作。
And you did not mention the other place where you use users
referring object; 而且,您没有提到在其他地方使用users
引用对象的地方。 how are users
populated. users
如何填充。
It seams that problem is not that code gets stuck but it throws exception which is handled silently by theadpool. 它表明问题不是代码卡住了,而是引发了异常,该异常由theadpool静默处理。 I tried to push custom ThreadFactory with logging enabling but it still doesn't works. 我尝试在启用日志记录的情况下推送自定义ThreadFactory,但仍然无法正常工作。 solution is to provide proper try catching for RuntimeException s 解决方案是为RuntimeException提供适当的尝试捕获
So lesson I've learned is that if part of your code doesn't get executed inside threadpool it might be because of the RuntimeException and you should provide more try catching to find the cause 因此,我吸取的教训是,如果您的部分代码未在线程池中执行,则可能是由于RuntimeException所致,您应该提供更多尝试捕获以找出原因
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.