多线程Java ConcurrentSkipListMap在某些线程中卡住
我有这个容器
private ConcurrentMap<Integer,SortedMap<Long,Object>> users;
在构造函数users = new ConcurrentHashMap<>();
中初始化
对于每个用户,它得到new ConcurrentSkipListMap<>()
我有一个在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");
}
使用executorService = Executors.newScheduledThreadPool(8);
调用此方法
executorService.execute(new Runnable() {
@Override
public void run() {
process(obj);
}
});
有时它工作得很好,但有时(我想是在高负载情况下)某些用户进程方法(所有调用)会被卡住,永远不会输出第2节
如果我交换q.headMap( someNumber ).clear();
和q.put( obj.someId, obj );
它仍然没有输出第2节
我也尝试了LinkedBlockingQueue
而不是ConcurrentSkipListMap
,但我有同样的问题
它看起来像一个死锁,但我没有在该结构上使用任何同步语句
如果你有想法,请分享你的想法
# 1 楼答案
可能有多种原因;最明显的是不同步的代码。进行线程转储以轻松确定原因
一些问题:
在
ConcurrentSkipListMap
JavaDocs中,它在headMap()
中说:因此,如果
obj.someId.compareTo(someNumber) < 0
,你可以在put()
得到一个IllegalArgumentException
,它在任何地方都不会被治疗这也会导致比赛条件:
如果两个线程都有
(thread1) someNumber = (thread2) obj.someId
,那么你就会得到一个竞争条件,谁知道下面会发生什么。此外,正如JavaDocs所说clear()
不是原子操作你没有提到你使用
users
指代对象的另一个地方;如何填充users
# 2 楼答案
问题不在于代码被卡住,而是它抛出异常,异常由ADPool静默处理。我试图通过启用日志功能来推动定制ThreadFactory,但它仍然不起作用。解决方案是为运行时异常提供适当的尝试捕获
所以我学到的教训是,如果部分代码没有在线程池中执行,可能是因为RuntimeException,您应该提供更多的try Catch来查找原因