why Threads get blocked when i use Apache-Commons-Pool?

1.4k Views Asked by At

Here is my demo:

PoolableObjectFactoryImpl.java

public class PoolableObjectFactoryImpl implements PoolableObjectFactory<Result> {

private static Logger logger = Logger.getLogger("BackgroundLog");

@Override
public void activateObject(Result obj) throws Exception {
    logger.info("==activate result.==");
    obj.setResult(-999);
}

@Override
public void destroyObject(Result obj) throws Exception {
    logger.info("==destroy result.==");
    obj = null;
}

@Override
public Result makeObject() throws Exception {
    logger.info("==make result.==");
    Result result = new Result();
    return result;
}

@Override
public void passivateObject(Result obj) throws Exception {
    logger.info("==passivate result.==");
    obj.setResult(-999);
}

@Override
public boolean validateObject(Result obj) {
    /*if(obj.getResult() == -999){
        logger.info("==validate result true.==");
        return true;
    }else{
        logger.info("==validate result false.==");
        return false;
    }*/
    logger.info("==validate result true.==");
    return true;
}

}

ThreadPool.java

public class ThreadPool extends GenericObjectPool {

private static Logger logger = Logger.getLogger("BackgroundLog");

private static ThreadPool pool = null;

private Map<String, String> map = getConfig();


private ThreadPool() {

    this.setFactory(new PoolableObjectFactoryImpl());

    this.setMaxActive(Integer.parseInt(map.get("maxActive")));

    this.setWhenExhaustedAction(Byte.valueOf(map.get("whenExhaustedAction")));

    this.setMaxWait(Long.parseLong(map.get("maxWait")));

    this.setMaxIdle(Integer.parseInt(map.get("maxIdle")));

    this.setTestOnBorrow(Boolean.valueOf(map.get("testOnBorrow")));

    this.setTestOnReturn(Boolean.valueOf(map.get("testOnReturn")));
    this.setTimeBetweenEvictionRunsMillis(Long.parseLong(map.get("timeBetweenEvictionRunsMillis")));

    this.setNumTestsPerEvictionRun(Integer.parseInt(map.get("numTestsPerEvictionRun")));
    this.setMinEvictableIdleTimeMillis(Long.parseLong(map.get("minEvictableIdleTimeMillis")));

    this.setTestWhileIdle(Boolean.valueOf(map.get("testWhileIdle")));


}


public static ThreadPool getInstance() {
    if (pool == null) {
        synchronized (ThreadPool.class) {
            if (pool == null) {
                logger.info("thread pool is initialized.");
                pool = new ThreadPool();
            }
        }
    }
    return pool;
}

/**
 * 
 * <p>Title: getConfig</p>
 * <p>Description: get pool configuration</p>
 * @return
 */
public Map<String, String> getConfig() {
    Map<String, String> map = new HashMap<String, String>();
    Properties props = new Properties();
    try {
        InputStream in = Thread.currentThread().getContextClassLoader().getResourceAsStream("pool.properties");
        props.load(in);
        Enumeration en = props.propertyNames();
        while (en.hasMoreElements()) {
            String key = (String) en.nextElement();
            map.put(key, props.getProperty(key));
        }
        in.close();
    } catch (Throwable t) {
        logger.error(t.getMessage(), t);
    }
    return map;
}
}

Result.java

public class Result {

private int result;

public Result(){
}

public int getResult(){
    return this.result;
}

public void setResult(int result){
    this.result = result;
}

}

Test.java

public class Test implements Runnable {

private static Logger logger = Logger.getLogger("BackgroundLog");

private String name = null;

public Test(String name){
    this.name = name;
}

public String getName(){
    return this.name;
}

public void setName(String name){
    this.name = name;
}

@Override
public void run() {
    ThreadPool pool = ThreadPool.getInstance();
    for(int i=0;i<1000;i++){
        try {
                Result result = (Result)pool.borrowObject();
                logger.info("numActive: "+ pool.getNumActive()+"\t"+"numIdle: "+pool.getNumIdle());
                logger.info("thread "+getName()+" "+i+" borrow object from pool "+result.getResult()+".");
                result.setResult(0);
                pool.returnObject(result);
                logger.info("return object to pool.");
                Thread.sleep(100);
        } catch (Exception e) {
            logger.info("thread "+getName()+" "+i);
            e.printStackTrace();
        }
    }
}

public static void main(String[] args) {
    for(int i=0;i<50;i++){
        Thread t = new Thread(new Test("t"+i));
        t.start();
    }
}
}

Next is the configuration properties:

enter image description here

Next is the threads view from Jprofiler when it has 4 threads:

enter image description here

After Test.java is running a few minutes,some threads keep beling blocked,only one is still running but does not print any log.I don't really understand thread thing. can anyone explain why? how to avoid threads being blocked?

2

There are 2 best solutions below

0
On

Consider posting logs of an execution cycle.

Did you try commenting Thread.sleep line, because sleep will hold onto the lock it has acquired till the thread is in sleep mode.

0
On

Try replacing "Thread.sleep(100);" with:

            try {
                synchronized (this) {
                        this.wait(200);
                }
            } catch (InterruptedException e) {
            }