Yes, the evictor thread will not run by default. The reason is that the values of maxIdle and maxTotal are the same by default, which means that there will be no idle connections to close immediately, and no need in evicting. So, the pool just saves some resources by not running a useless thread.

But when you change maxIdle and make it lower than maxTotal without starting the evictor thread, it doesn't mean that your connections will not be closed. It means that they will be closed immediately after releasing, with no delay, until their count not drop down to maxIdle.

And then minEvictableIdleTimeMillis and softMinEvictableIdleTimeMillis come to play (be careful, there's a typo in the documentation, it's ...MinEvictalbe..., not ...MiniEvictable...). The difference between them is that the former doesn't respect minIdle while the latter does. It's a bit tricky given the fact that softMinEvictableIdleTimeMillis is only checked when minEvictableIdleTimeMillis has elapsed.

Let's assume we have minEvictableIdleTimeMillis=10000 and softMinEvictableIdleTimeMillis=-1 (by default). In such case an idle connection will remain in the pool for no longer than 10 seconds. Even if the number of connections does not exceed minIdle, it will be closed. If it lead to dropping of the connections count lower than minIdle, a new connection will be created immediately.

Now, let's assume that we have minEvictableIdleTimeMillis=10000 and softMinEvictableIdleTimeMillis=30000. In such case an idle connection after checking against minEvictableIdleTimeMillis and detection of exceeding will be additionally checked against softMinEvictableIdleTimeMillis. If the idle time exceeds it, the connection will be closed. Otherwise, it will sit in the pool till the next positive check against minEvictableIdleTimeMillis.

Eventually, you'll have connections between maxTotal and maxIdle closed immediately, connections between maxIdle and minIdle closed after minEvictableIdleTimeMillis and connections between minIdle and 0 closed after softMinEvictableIdleTimeMillis and reopened immediately. Give or take the eviction check period.

With your configuration, you will have all the connections closed immediately while the pool is larger than 20. And those 20 connections will live from 10 to 20 minutes (even if idle) because you have 10 minutes of both EvictableIdleTimeMillis plus 10 minutes of TimeBetweenEvictionRunsMillis.

Email codedump link for DBCP2 - When are Idle connections removed from the Pool