4

我有一个运行多线程的tomcat - spring4.2应用程序。每个线程仅从一个队列中出队,但是有多个线程分配给一个队列。Redis队列中的'停车等待'状态线程

事情开始很好,但经过几个小时/〜500k的出列操作,我发现线程以极低的速度出队。

在jvisualvm我看到橙色即螺纹停放 的线程转储如下:

"EMLT_2" - Thread [email protected] 
    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 [email protected] 
    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; 
     } 
    } 

将理解输入。该应用程序在重新启动后再次运行良好。 Pool conf:

<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> 
+0

认为这是一个连接泄漏,但尝试资源不应该这样做。 –

+0

经过所有的研究发现,游泳池被注入一个班级,长时间书写和遗忘,并有连接泄漏。愚蠢。 –

回答

1

看起来您的jedis池已经没有连接了。 您是否正在使用returnResourceObject或returnResource返回资源? (我知道两者都被弃用,但他们仍然使用jedis的版本)。

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

我有一个类似的问题,它结束了,当我调用上述方法。另一方面,由于Redis速度非常快,也许你应该重新思考你的模式,并且很少有线程调用blpop(每个队列一个)并将值转发给其他线程,所以那些不知道关于redis如果他们不需要。

+0

即使我这么认为,但我该如何验证?我没有做任何特别的事情,除了尝试(Jedis jedis = jedispool.getResource()){'我需要明确调用这些方法吗? –

+0

至少在我的情况下,我不得不,但它不会工作。 –

+0

想转向生菜。 '最后{ \t \t \t如果(jedis!= NULL){ \t \t \t \t jedispool.returnResourceObject(jedis); \t \t \t} \t \t}'没有帮助 –