commons-collections-3.2.jarhtml
分析:Redis的JavaAPI中Jedis错误,看到这个你确定会以为这个问题有点低级,确实低级,不用看都知道是少导了jar包引发的,不过这不是重点,重点是Jedis中的一个方法:pool.returnResource(jedis);这个才是重点中的重点,接下来咱们看看这个方法的描述:voidredis.clients.util.Pool.returnResource(Jedis jedis)能够看出这里面并无抛出异常的声明子类的,那咱们就不会去try-catch了,不去try-catch的后果就是会出现莫名其妙的错误,不try-catch会出现一个java.lang.NullPointerExceptio这样的空指针异常,这样的信息给咱们是没用的,这是咱们缺乏jar包致使的问题,这里却提示java.lang.NullPointerException这样的空指针异常,这不是坑爹么?(彻底不是咱们想要的东西)、、、而后就开始坑爹了,本身开始找错误了,运气差的话找N久也找不出来,有一种怒砸电脑的冲动,运气好的话一下就把错误找出来了,请看下面的代码,不用try-catch跟使用try-catch的比较。饿当时就没使用try-catch,由于这个方法pool.returnResource(jedis);没有声明有异常抛出,因此天然不会用。(坑爹啊!)java
缘由:缺乏commons-collections-3.2.jar这样的jar包redis
解决:导入commons-collections-3.2.jar该jar包就好了apache
# 没有使用try-catch的代码已经相应的异常信息spa
publicvoid hdel(String key, String field){.net
JedisPoolpool =null;线程
Jedisjedis =null;指针
try {code
pool= getJedisPool(key);htm
jedis= pool.getResource();
jedis.hdel(key,field);
}catch (Exception e) {
log.error("Redis hdel exception :" + key, e);
pool.returnBrokenResource(jedis);
}finally {
pool.returnResource(jedis);
}
java.lang.NullPointerException
atcn.adsit.iva.preroll.dp.synch.analysis.redis.util.ConsistentHashRedisUtils.hset(ConsistentHashRedisUtils.java:164)
atcn.adsit.iva.preroll.dp.synch.analysis.UserBehaviorStoreRedis.userBehavior2Redis(UserBehaviorStoreRedis.java:58)
atcn.adsit.iva.preroll.dp.synch.analysis.UserBehaviorAnalysisMainClass.main(UserBehaviorAnalysisMainClass.java:33)
public void hdel(String key, String field) {
JedisPool pool =null;
Jedis jedis =null;
try {
pool = getJedisPool(key);
jedis = pool.getResource();
jedis.hdel(key, field);
} catch (Exception e) {
log.error("Redis hdel exception : " +key, e);
pool.returnBrokenResource(jedis);
} finally {
try {
pool.returnResource(jedis);
}catch(Exception e) {
log.error("JdisreturnResource exception : ", e);
}
}
[2014-07-1016:39:17,659].[ERROR].[cn.adsit.iva.preroll.dp.synch.analysis.redis.util.ConsistentHashRedisUtils]
JdisreturnResource exception :
java.lang.NullPointerException
atcn.adsit.iva.preroll.dp.synch.analysis.redis.util.ConsistentHashRedisUtils.hset(ConsistentHashRedisUtils.java:164)
atcn.adsit.iva.preroll.dp.synch.analysis.UserBehaviorStoreRedis.userBehavior2Redis(UserBehaviorStoreRedis.java:58)
atcn.adsit.iva.preroll.dp.synch.analysis.UserBehaviorAnalysisMainClass.main(UserBehaviorAnalysisMainClass.java:33)
Exception in thread"main" java.lang.NoClassDefFoundError:org/apache/commons/collections/CursorableLinkedList
atorg.apache.commons.pool.impl.GenericObjectPool.<init>(GenericObjectPool.java:392)
atorg.apache.commons.pool.impl.GenericObjectPool.<init>(GenericObjectPool.java:275)
atredis.clients.util.Pool.<init>(Pool.java:14)
atredis.clients.jedis.JedisPool.<init>(JedisPool.java:24)
atredis.clients.jedis.JedisPool.<init>(JedisPool.java:29)
atcn.adsit.iva.preroll.dp.synch.analysis.redis.util.ConsistentHashRedisUtils.getJedisPool(ConsistentHashRedisUtils.java:343)
atcn.adsit.iva.preroll.dp.synch.analysis.redis.util.ConsistentHashRedisUtils.getJedisPool(ConsistentHashRedisUtils.java:317)
atcn.adsit.iva.preroll.dp.synch.analysis.redis.util.ConsistentHashRedisUtils.hset(ConsistentHashRedisUtils.java:156)
atcn.adsit.iva.preroll.dp.synch.analysis.UserBehaviorStoreRedis.userBehavior2Redis(UserBehaviorStoreRedis.java:58)
atcn.adsit.iva.preroll.dp.synch.analysis.UserBehaviorAnalysisMainClass.main(UserBehaviorAnalysisMainClass.java:33)
Caused by:java.lang.ClassNotFoundException:org.apache.commons.collections.CursorableLinkedList
atjava.net.URLClassLoader$1.run(URLClassLoader.java:217)
atjava.security.AccessController.doPrivileged(Native Method)
atjava.net.URLClassLoader.findClass(URLClassLoader.java:205)
atjava.lang.ClassLoader.loadClass(ClassLoader.java:319)
atjava.lang.ClassLoader.loadClass(ClassLoader.java:264)
atjava.lang.ClassLoader.loadClassInternal(ClassLoader.java:332)
... 10more
}
对比能够知道,使用try-catch以后能够看到原来看不到的更重要的异常信息:Caused by: java.lang.ClassNotFoundException:org.apache.commons.collections.CursorableLinkedList
,而后咱们就知道是导入commons-collections-3.2.jar这样的jar包了,而后就搞定了,不解释,一个坑爹的问题,缺乏jar包,也能够说是本身粗心吧!
但愿能够帮到也碰到这样问题的朋友、、、
public void testGet() { Jedis jedis = null; try { // 从池中获取一个jedis实例 jedis = jedisPool.getResource(); System.out.println(jedis.get("blog_pool")); } catch (Exception e) { // 销毁对象 jedisPool.returnBrokenResource(jedis); Assert.fail(e.getMessage()); } finally { // 还会到链接池 jedisPool.returnResource(jedis); } }
package com.ljq.utils; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; /** * Redis操做接口 * * @author 林计钦 * @version 1.0 2013-6-14 上午08:54:14 */ public class RedisAPI { private static JedisPool pool = null; /** * 构建redis链接池 * * @param ip * @param port * @return JedisPool */ public static JedisPool getPool() { if (pool == null) { JedisPoolConfig config = new JedisPoolConfig(); //控制一个pool可分配多少个jedis实例,经过pool.getResource()来获取; //若是赋值为-1,则表示不限制;若是pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted(耗尽)。 config.setMaxActive(500); //控制一个pool最多有多少个状态为idle(空闲的)的jedis实例。 config.setMaxIdle(5); //表示当borrow(引入)一个jedis实例时,最大的等待时间,若是超过等待时间,则直接抛出JedisConnectionException; config.setMaxWait(1000 * 100); //在borrow一个jedis实例时,是否提早进行validate操做;若是为true,则获得的jedis实例均是可用的; config.setTestOnBorrow(true); pool = new JedisPool(config, "192.168.2.191", 8888); } return pool; } /** * 返还到链接池 * * @param pool * @param redis */ public static void returnResource(JedisPool pool, Jedis redis) { if (redis != null) { pool.returnResource(redis); } } /** * 获取数据 * * @param key * @return */ public static String get(String key){ String value = null; JedisPool pool = null; Jedis jedis = null; try { pool = getPool(); jedis = pool.getResource(); value = jedis.get(key); } catch (Exception e) { //释放redis对象 pool.returnBrokenResource(jedis); e.printStackTrace(); } finally { //返还到链接池 returnResource(pool, jedis); } return value; } }
代码说明:
a、获取jedis实例时,实际上可能有两类错误。
一类是pool.getReource(),得不到可用的jedis实例;
另外一类是jedis.set/get时出错也会抛出异常;
为了实现区分,因此根据instance是否为null来实现,若是为空就证实instance根本就没初始化,也就不用return给pool;若是instance不为null,则证实是须要返还给pool的;
b、在instance出错时,必须调用returnBrokenResource返还给pool,不然下次经过getResource获得的instance的缓冲区可能还存在数据,出现问题!
-------------------------------------------------
JedisPool的配置参数很大程度上依赖于实际应用需求、软硬件能力。之前没用过commons-pool,因此此次花了一成天专门看这些参数的含义。。。JedisPool的配置参数大部分是由JedisPoolConfig的对应项来赋值的。
maxActive:控制一个pool可分配多少个jedis实例,经过pool.getResource()来获取;若是赋值为-1,则表示不限制;若是pool已经分配了maxActive个jedis实例,则此时pool的状态为exhausted。
maxIdle:控制一个pool最多有多少个状态为idle(空闲)的jedis实例;
whenExhaustedAction:表示当pool中的jedis实例都被allocated完时,pool要采起的操做;默认有三种。
WHEN_EXHAUSTED_FAIL --> 表示无jedis实例时,直接抛出NoSuchElementException;
WHEN_EXHAUSTED_BLOCK --> 则表示阻塞住,或者达到maxWait时抛出JedisConnectionException;
WHEN_EXHAUSTED_GROW --> 则表示新建一个jedis实例,也就说设置的maxActive无用;
maxWait:表示当borrow一个jedis实例时,最大的等待时间,若是超过等待时间,则直接抛出JedisConnectionException;
testOnBorrow:在borrow一个jedis实例时,是否提早进行alidate操做;若是为true,则获得的jedis实例均是可用的;
testOnReturn:在return给pool时,是否提早进行validate操做;
testWhileIdle:若是为true,表示有一个idle object evitor线程对idle object进行扫描,若是validate失败,此object会被从pool中drop掉;这一项只有在timeBetweenEvictionRunsMillis大于0时才有意义;
timeBetweenEvictionRunsMillis:表示idle object evitor两次扫描之间要sleep的毫秒数;
numTestsPerEvictionRun:表示idle object evitor每次扫描的最多的对象数;
minEvictableIdleTimeMillis:表示一个对象至少停留在idle状态的最短期,而后才能被idle object evitor扫描并驱逐;这一项只有在timeBetweenEvictionRunsMillis大于0时才有意义;
softMinEvictableIdleTimeMillis:在minEvictableIdleTimeMillis基础上,加入了至少minIdle个对象已经在pool里面了。若是为-1,evicted不会根据idle time驱逐任何对象。若是minEvictableIdleTimeMillis>0,则此项设置无心义,且只有在timeBetweenEvictionRunsMillis大于0时才有意义;
lifo:borrowObject返回对象时,是采用DEFAULT_LIFO(last in first out,即相似cache的最频繁使用队列),若是为False,则表示FIFO队列;
其中JedisPoolConfig对一些参数的默认设置以下: testWhileIdle=true minEvictableIdleTimeMills=60000 timeBetweenEvictionRunsMillis=30000 numTestsPerEvictionRun=-1