Java ConcurrentSkipListMap陷入了一些线程

时间:2015-04-16 07:37:21

标签: java multithreading concurrency deadlock

我有这个容器

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,但我有同样的问题

它看起来像死锁,但我没有在该结构上使用任何同步语句。

如果你有一个

,请分享你的想法

2 个答案:

答案 0 :(得分:2)

可能有多种原因;最明显的一个是非同步代码。采用线程转储来轻松识别原因。

一些问题:

ConcurrentSkipListMap JavaDocs中它在headMap()处说:

The returned map will throw an IllegalArgumentException on an attempt to insert a key outside its range.

因此,如果obj.someId.compareTo(someNumber) < 0您可以在IllegalArgumentException获得put(),而且不会在任何地方受到处理。

这也会导致竞争条件:

q.headMap( someNumber ).clear();
q.put( obj.someId, obj )

如果两个线程有​​(thread1) someNumber = (thread2) obj.someId,你就会遇到竞争条件,并且知道底层会发生什么。此外,正如JavaDocs所说,clear()不是原子操作。

你没有提到你使用users引用对象的另一个地方;如何填充users

答案 1 :(得分:0)

它接缝问题不是代码卡住但它抛出异常,由theadpool静默处理。我试图推送自定义ThreadFactory与日志启用,但它仍然无法正常工作。解决方案是为RuntimeException提供正确的try catch

我所学到的教训是,如果你的部分代码没有在线程池中执行,那么可能是因为RuntimeException,你应该提供更多尝试来查找原因