线程在 Redis 取消排队时处于'parking to wait'状态



我有一个tomcat-spring4.2应用程序,它运行多个线程。每个线程只从一个队列中出列,但是有多个线程分配给一个队列。

事情一开始很好,但经过几个小时/~500k次出列操作后,我发现线程出列的速度非常慢。

在jvisualvm中,我看到橙色的线程,即park线程转储如下:

"EMLT_2" - Thread t@64
   java.lang.Thread.State: WAITING
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for <2cf42d7> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
    at org.apache.commons.pool2.impl.LinkedBlockingDeque.takeFirst(LinkedBlockingDeque.java:583)
    at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:442)
    at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:363)
    at redis.clients.util.Pool.getResource(Pool.java:48)
    at redis.clients.jedis.JedisPool.getResource(JedisPool.java:86)
    at com.mycomp.sam.processors.SimpleDequeuer.dequeue(SimpleDequeuer.java:25)
    at com.mycomp.sam.processors.EMLT.run(EMLT.java:29)
    at java.lang.Thread.run(Thread.java:745)
   Locked ownable synchronizers:
    - None
"EMLT_1" - Thread t@63
   java.lang.Thread.State: WAITING
    at sun.misc.Unsafe.park(Native Method)
    - parking to wait for <2cf42d7> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
    at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
    at org.apache.commons.pool2.impl.LinkedBlockingDeque.takeFirst(LinkedBlockingDeque.java:583)
    at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:442)
    at org.apache.commons.pool2.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:363)
    at redis.clients.util.Pool.getResource(Pool.java:48)
    at redis.clients.jedis.JedisPool.getResource(JedisPool.java:86)
    at com.mycomp.sam.processors.SimpleDequeuer.dequeue(SimpleDequeuer.java:25)
    at com.mycomp.sam.processors.EMLT.run(EMLT.java:29)
    at java.lang.Thread.run(Thread.java:745)
   Locked ownable synchronizers:
    - None

出队方法是:

public String dequeue(String queue) {
        try (Jedis jedis = jedispool.getResource()) {
            List<String> str = jedis.blpop(10, queue);
            if(str!=null){
                return str.get(1);
            }
            else 
                return null; 
        }
    }

将感谢您的投入。该应用程序在重新启动后的一段时间内再次运行良好。池配置:

<bean id="poolConfig" class="redis.clients.jedis.JedisPoolConfig">
    <property name="maxIdle" value="10" />
    <property name="maxTotal" value="70" />
    <property name="minIdle" value="10" />
</bean>
<bean id="jedispool" class="redis.clients.jedis.JedisPool">
    <constructor-arg name="poolConfig" ref="poolConfig" />
    <constructor-arg name="host" value="${REDIS_HOST}" />
    <constructor-arg name="port" value="6379" />
</bean>

您的jedis池似乎没有连接了。您是使用returnResourceObject还是returnResource返回资源?(我知道两者都被弃用了,但它们仍然适用于最新版本的jedis)。

请记住,jedis池并不完全像DBCP/Apache池。

我也遇到过类似的问题,当我调用上面的方法时,它就结束了。

另一方面,由于Redis速度很快,也许你应该重新思考你的模式,很少有线程调用blpop(每个队列一个),并将值转发给其他线程,所以如果不需要的话,这些线程就不知道Redis

最新更新