1. What is an object pool
The life cycle of an object can be roughly divided into three stages: create - > use - > destroy. The time of this object is T1 (create) + T2 (use) + T3 (destroy), If this step is required to create N objects, it must be time-consuming and performance consuming. The official explanation of object pool is:
Save the used objects and reuse them the next time you need them, so as to reduce the overhead caused by frequent object creation to a certain extent. It is used as a "container" object for saving objects, which is called "object pool".
2. Creation of jedispool
Jedis's connection pool is based on Apache common. Pool2, so the implementation of jedisPool is based on pool2. The source code document of pool2 can be referred to http://commons.apache.org/proper/commons-pool/

JedisPool is a subclass of the Pool abstract class.
public class JedisPoolAbstract extends Pool<Jedis> { ... }
The JedisPool constructor finally calls the method of Pool#initPool
package redis.clients.jedis.util; public abstract class Pool<T> implements Closeable { protected GenericObjectPool<T> internalPool; public Pool(final GenericObjectPoolConfig poolConfig, PooledObjectFactory<T> factory) { initPool(poolConfig, factory); } @Override public void close() { destroy(); } public boolean isClosed() { return this.internalPool.isClosed(); } public void initPool(final GenericObjectPoolConfig poolConfig, PooledObjectFactory<T> factory) { if (this.internalPool != null) { try { closeInternalPool(); } catch (Exception e) { } } # Instantiate GenericeObjectPool in pool2 this.internalPool = new GenericObjectPool<T>(factory, poolConfig); } # Get and release Jedis instances from JedisPool, public T getResource() { try { # Read source location org.apache.commons.pool2.impl#borrowObject return internalPool.borrowObject(); } catch (NoSuchElementException nse) { if (null == nse.getCause()) { // The exception was caused by an exhausted pool throw new JedisExhaustedPoolException( "Could not get a resource since the pool is exhausted", nse); } // Otherwise, the exception was caused by the implemented activateObject() or ValidateObject() throw new JedisException("Could not get a resource from the pool", nse); } catch (Exception e) { throw new JedisConnectionException("Could not get a resource from the pool", e); } } protected void returnResourceObject(final T resource) { if (resource == null) { return; } try { internalPool.returnObject(resource); } catch (Exception e) { throw new JedisException("Could not return the resource to the pool", e); } }
The initPool method has two parameters: a GenericObjectPoolConfig configuration item encapsulation class, and a PooledObjectFactory factory class to obtain jedis connection objects from the connection pool after obtaining the connection pool. Instantiate the GenericeObjectPool in pool2 according to the configuration information, which is the manager of the object pool.
When getResource is called to obtain Jedis, the internalPool inside the Pool actually calls borowobject() to get an instance, and the GenericObjectPool of internalPool calls makeObject() of JedisFactory to complete the generation of the instance (when there are not enough resources in the Pool)
How is Jedis instantiated
Let's take a look at the source code of JedisFactory
class JedisFactory implements PooledObjectFactory<Jedis> { @Override public PooledObject<Jedis> makeObject() throws Exception { final HostAndPort hostAndPort = this.hostAndPort.get(); final Jedis jedis = new Jedis(hostAndPort.getHost(), hostAndPort.getPort(), connectionTimeout, soTimeout, ssl, sslSocketFactory, sslParameters, hostnameVerifier); try { jedis.connect(); if (password != null) { jedis.auth(password); } if (database != 0) { jedis.select(database); } if (clientName != null) { jedis.clientSetname(clientName); } } catch (JedisException je) { jedis.close(); throw je; } return new DefaultPooledObject<Jedis>(jedis); } ... }
JedisFactory implements the PooledObjectFactory interface of pool2, and the interface for creating and destroying objects in the pool is handed over to the business party (that is, JedisFactory in this paper). A Jedis object is created in the JedisFactory#makeObject() method. Jedis inherits from BinaryJedis. It has a Client attribute. The Client is a subclass of Connection. The Connection has the attribute socket, which is the class that really creates a Connection with the redis server, and the socket is a long Connection.

redis.clients.jedis.Connection#connect
public void connect() { if (!isConnected()) { try { socket = new Socket(); // ->@wjw_add socket.setReuseAddress(true); #Establish long connection socket.setKeepAlive(true); // Will monitor the TCP connection is // valid socket.setTcpNoDelay(true); // Socket buffer Whetherclosed, to // ensure timely delivery of data socket.setSoLinger(true, 0); // Control calls close () method, // the underlying socket is closed // immediately // <-@wjw_add socket.connect(new InetSocketAddress(host, port), connectionTimeout); socket.setSoTimeout(soTimeout); ...... outputStream = new RedisOutputStream(socket.getOutputStream()); inputStream = new RedisInputStream(socket.getInputStream()); } catch (IOException ex) { broken = true; throw new JedisConnectionException("Failed connecting to host " + host + ":" + port, ex); } } }
From the above source code, we can see that Jedis and the network connection are bound one by one. If the redis object is GC, its client and socket connections will be destroyed together.
Client return object pool
The processing rules of the return pool are implemented by common-pool2, which is to put the jedis object into the idle queue. If the queue is full, it will be destroyed directly. The destruction is implemented in JedisFactory redis.clients.jedis.JedisFactory#destroyObject
@Override public void destroyObject(PooledObject<Jedis> pooledJedis) throws Exception { final BinaryJedis jedis = pooledJedis.getObject(); if (jedis.isConnected()) { try { try { jedis.quit(); } catch (Exception e) { } jedis.disconnect(); } catch (Exception e) { } } }
When the socket connection is actively closed, the generic object pool in common-pool2 will also remove it from the free pool and the total pool.