使用Jakarta Commons Pool对象池技术
1. 为什么使用对象池技术 创建新的对象并初始化,可能会消耗很多时间。在这种对象的初始化工作中如果依赖一些rpc远程调用来创建对象,例如通过socket或者http连接远程服务资源,最典型的就是数据库服务以及远程队列(Remote Queue),建立连接 - 发送数据 -
1. 为什么使用对象池技术
创建新的对象并初始化,可能会消耗很多时间。在这种对象的初始化工作中如果依赖一些rpc远程调用来创建对象,例如通过socket或者http连接远程服务资源,最典型的就是数据库服务以及远程队列(Remote Queue),建立连接 -> 发送数据 -> 接收连接 -> 释放连接的过程无疑对于客服端来说相当繁重。在需要大量或者频繁生成这样的对象的时候,就可能会对性能造成一些不可忽略的影响。要解决这个问题在软件层面上可以使用对象池技术(Object Pooling),而Jakarta Commons Pool框架则是处理对象池化的有力外援。
2. 对象池技术解释
对象池的基本思路是:将用过的对象保存起来,等下一次需要这种对象的时候,再拿出来重复使用,从而在一定程度上减少频繁创建对象所造成的开销。用于充当保存对象的“容器”的对象,被称为“对象池”(Object Pool,或简称Pool)。
并非所有对象都适合拿来池化――因为维护对象池也要造成一定开销。对生成时开销不大的对象进行池化,反而可能会出现“维护对象池的开销”大于“生成新对象的开销”,从而使性能降低的情况。但是对于生成时开销可观的对象,池化技术就是提高性能的有效策略了。
3. Jakarta Commons Pool对象池框架
在该框架中,主要工作有两类对象:
PoolableObjectFactory:用于管理被池化的对象的产生、激活、挂起、校验和销毁;
ObjectPool:用于管理要被池化的对象的借出和归还,并通知PoolableObjectFactory完成相应的工作;
相应地,使用Pool框架的过程,也就划分成“创立PoolableObjectFactory”、“使用ObjectPool”两种动作。
3.1 使用PoolableObjectFactory
Pool框架利用PoolableObjectFactory来管理被池化的对象。ObjectPool的实例在需要处理被池化的对象的产生、激活、挂起、校验和销毁工作时,就会调用跟它关联在一起的PoolableObjectFactory实例的相应方法来操作。
PoolableObjectFactory是在org.apache.commons.pool包中定义的一个接口。实际使用的时候需要利用这个接口的一个具体实现。Pool框架本身没有包含任何一种PoolableObjectFactory实现,需要根据情况自行创立。
创立PoolableObjectFactory的大体步骤是:
创建一个实现了PoolableObjectFactory接口的类。
import org.apache.commons.pool.PoolableObjectFactory;
public class PoolableObjectFactorySample
implements PoolableObjectFactory {
private static int counter = 0;
}
为这个类添加一个Object makeObject()方法。这个方法用于在必要时产生新的对象。
public Object makeObject() throws Exception {
Object obj = String.valueOf(counter++);
System.err.println("Making Object " + obj);
return obj;
}
为这个类添加一个void activateObject(Object obj)方法。这个方法用于将对象“激活”――设置为适合开始使用的状态。
public void activateObject(Object obj) throws Exception {
System.err.println("Activating Object " + obj);
}
为这个类添加一个void passivateObject(Object obj)方法。这个方法用于将对象“挂起”――设置为适合开始休眠的状态。
public void passivateObject(Object obj) throws Exception {
System.err.println("Passivating Object " + obj);
}
为这个类添加一个boolean validateObject(Object obj)方法。这个方法用于校验一个具体的对象是否仍然有效,已失效的对象会被自动交给destroyObject方法销毁
public boolean validateObject(Object obj) {
boolean result = (Math.random() > 0.5);
System.err.println("Validating Object "
+ obj + " : " + result);
return result;
}
为这个类添加一个void destroyObject(Object obj)方法。这个方法用于销毁被validateObject判定为已失效的对象。
public void destroyObject(Object obj) throws Exception {
System.err.println("Destroying Object " + obj);
}
最后完成的PoolableObjectFactory类似这个样子:
import org.apache.commons.pool.PoolableObjectFactory; public class PoolableObjectFactorySample implements PoolableObjectFactory { private static int counter = 0; public Object makeObject() throws Exception { Object obj = String.valueOf(counter++); System.err.println("Making Object " + obj); return obj; } public void activateObject(Object obj) throws Exception { System.err.println("Activating Object " + obj); } public void passivateObject(Object obj) throws Exception { System.err.println("Passivating Object " + obj); } public boolean validateObject(Object obj) { /* 以1/2的概率将对象判定为失效 */ boolean result = (Math.random() > 0.5); System.err.println("Validating Object " + obj + " : " + result); return result; } public void destroyObject(Object obj) throws Exception { System.err.println("Destroying Object " + obj); } }
3.2 使用ObjectPool
有了合适的PoolableObjectFactory之后,便可以开始请出ObjectPool来与之同台演出了。
ObjectPool是在org.apache.commons.pool包中定义的一个接口,实际使用的时候也需要利用这个接口的一个具体实现。Pool框架本身包含了若干种现成的ObjectPool实现,可以直接利用。如果都不合用,也可以根据情况自行创建。具体的创建方法,可以参看Pool框架的文档和源码。
ObjectPool的使用方法类似这样:
生成一个要用的PoolableObjectFactory类的实例。
PoolableObjectFactory factory = new PoolableObjectFactorySample();
利用这个PoolableObjectFactory实例为参数,生成一个实现了ObjectPool接口的类(例如StackObjectPool)的实例,作为对象池。
ObjectPool pool = new StackObjectPool(factory);
需要从对象池中取出对象时,调用该对象池的Object borrowObject()方法。
Object obj = null;
obj = pool.borrowObject();
需要将对象放回对象池中时,调用该对象池的void returnObject(Object obj)方法。
pool.returnObject(obj);
当不再需要使用一个对象池时,调用该对象池的void close()方法,释放它所占据的资源。
pool.close();
这些操作都可能会抛出异常,需要另外处理。
比较完整的使用ObjectPool的全过程,可以参考这段代码:
import org.apache.commons.pool.ObjectPool; import org.apache.commons.pool.PoolableObjectFactory; import org.apache.commons.pool.impl.StackObjectPool; public class ObjectPoolSample { public static void main(String[] args) { Object obj = null; PoolableObjectFactory factory = new PoolableObjectFactorySample(); ObjectPool pool = new StackObjectPool(factory); try { for(long i = 0; i <p>综上,UML图如下:</p> <p><img class="alignnone size-full wp-image-944 lazy" src="/static/imghw/default1.png" data-src="http://www.68idc.cn/help/uploads/allimg/150302/10540945H-0.gif" alt="" style="max-width:90%" title="1339989089_1857" style="max-width:90%"></p> <h3 id="线程安全问题">3.3 线程安全问题</h3> <p>有时候可能要在多线程环境下使用Pool框架,这时候就会遇到和Pool框架的线程安全程度有关的问题。</p> <p>因为ObjectPool和KeyedObjectPool都是在org.apache.commons.pool中定义的接口,而在接口中无法使用“synchronized”来修饰方法,所以,一个ObjectPool下的各个方法是否是同步方法,完全要看具体的实现。而且,单纯地使用了同步方法,也并不能使对象就此在多线程环境里高枕无忧。</p> <p>就Pool框架中自带的几个ObjectPool的实现而言,它们都在一定程度上考虑了在多线程环境中使用的情况。不过还不能说它们是完全“线程安全”的。</p> <p>例如,这段代码有些时候就会有一些奇怪的表现,最后输出的结果比预期的要大:</p> <p class="wp_syntax"></p><p class="code"></p><pre class="brush:php;toolbar:false">import org.apache.commons.pool.ObjectPool; import org.apache.commons.pool.impl.StackObjectPool; class UnsafePicker extends Thread { private ObjectPool pool; public UnsafePicker(ObjectPool op) { pool = op; } public void run() { Object obj = null; try { /* 似乎…… */ if ( pool.getNumActive() <p>要避免这种情况,就要进一步采取一些措施才行:</p> <p class="wp_syntax"></p><p class="code"></p><pre class="brush:php;toolbar:false">import org.apache.commons.pool.ObjectPool; import org.apache.commons.pool.impl.StackObjectPool; class SafePicker extends Thread { private ObjectPool pool; public SafePicker(ObjectPool op) { pool = op; } public void run() { Object obj = null; try { /* 略加处理 */ synchronized (pool) { if ( pool.getNumActive() <p>基本上,可以说Pool框架是线程相容的。但是要在多线程环境中使用,还需要作一些特别的处理。</p> <h2 id="Jedis中线程池的实例">4. Jedis中线程池的实例</h2> <p>下面看一个实例,由于近期在研究Redis,所以需要找一个可靠的redis驱动,有很多开源项目,详见链接,Jedis便是其中历史较早的。相比于其他驱动,Jedis提供了一个JedisPool用于管理redis连接的池,其主要工作的包括Pool.java,JedisPool.java和JedisPoolConfig.java。</p> <p>Pool.java封装了一个GenericObjectPool,负责Jedis连接的产生、校验和销毁。</p> <p class="wp_syntax"></p><p class="code"></p><pre class="brush:php;toolbar:false">package redis.clients.util; ? import org.apache.commons.pool.PoolableObjectFactory; import org.apache.commons.pool.impl.GenericObjectPool; import redis.clients.jedis.exceptions.JedisConnectionException; import redis.clients.jedis.exceptions.JedisException; ? public abstract class Pool { private final GenericObjectPool internalPool; ? public Pool(final GenericObjectPool.Config poolConfig, PoolableObjectFactory factory) { this.internalPool = new GenericObjectPool(factory, poolConfig); } ? @SuppressWarnings("unchecked") public T getResource() { try { return (T) internalPool.borrowObject(); } catch (Exception e) { throw new JedisConnectionException( "Could not get a resource from the pool", e); } } ? public void returnResourceObject(final Object resource) { try { internalPool.returnObject(resource); } catch (Exception e) { throw new JedisException( "Could not return the resource to the pool", e); } } ? public void returnBrokenResource(final T resource) { returnBrokenResourceObject(resource); } ? public void returnResource(final T resource) { returnResourceObject(resource); } ? protected void returnBrokenResourceObject(final Object resource) { try { internalPool.invalidateObject(resource); } catch (Exception e) { throw new JedisException( "Could not return the resource to the pool", e); } } ? public void destroy() { try { internalPool.close(); } catch (Exception e) { throw new JedisException("Could not destroy the pool", e); } } }
JedisPool.java继承了Pool.java,内部写了一个Inner Class – BasePoolableObjectFactory,用于新建JedisPool实例时传入线程池建立、销毁、验证连接的基本方法。
package redis.clients.jedis; ? import org.apache.commons.pool.BasePoolableObjectFactory; import org.apache.commons.pool.impl.GenericObjectPool.Config; ? import redis.clients.util.Pool; ? public class JedisPool extends Pool { ? public JedisPool(final Config poolConfig, final String host) { this(poolConfig, host, Protocol.DEFAULT_PORT, Protocol.DEFAULT_TIMEOUT, null, Protocol.DEFAULT_DATABASE); } ? public JedisPool(String host, int port) { this(new Config(), host, port, Protocol.DEFAULT_TIMEOUT, null, Protocol.DEFAULT_DATABASE); } ? public JedisPool(final String host) { this(host, Protocol.DEFAULT_PORT); } ? public JedisPool(final Config poolConfig, final String host, int port, int timeout, final String password) { this(poolConfig, host, port, timeout, password, Protocol.DEFAULT_DATABASE); } ? public JedisPool(final Config poolConfig, final String host, final int port) { this(poolConfig, host, port, Protocol.DEFAULT_TIMEOUT, null, Protocol.DEFAULT_DATABASE); } ? public JedisPool(final Config poolConfig, final String host, final int port, final int timeout) { this(poolConfig, host, port, timeout, null, Protocol.DEFAULT_DATABASE); } ? public JedisPool(final Config poolConfig, final String host, int port, int timeout, final String password, final int database) { super(poolConfig, new JedisFactory(host, port, timeout, password, database)); } ? ? public void returnBrokenResource(final BinaryJedis resource) { returnBrokenResourceObject(resource); } ? public void returnResource(final BinaryJedis resource) { returnResourceObject(resource); } ? /** * PoolableObjectFactory custom impl. */ private static class JedisFactory extends BasePoolableObjectFactory { private final String host; private final int port; private final int timeout; private final String password; private final int database; ? public JedisFactory(final String host, final int port, final int timeout, final String password, final int database) { super(); this.host = host; this.port = port; this.timeout = timeout; this.password = password; this.database = database; } ? public Object makeObject() throws Exception { final Jedis jedis = new Jedis(this.host, this.port, this.timeout); ? jedis.connect(); if (null != this.password) { jedis.auth(this.password); } if( database != 0 ) { jedis.select(database); } ? return jedis; } ? public void destroyObject(final Object obj) throws Exception { if (obj instanceof Jedis) { final Jedis jedis = (Jedis) obj; if (jedis.isConnected()) { try { try { jedis.quit(); } catch (Exception e) { } jedis.disconnect(); } catch (Exception e) { ? } } } } ? public boolean validateObject(final Object obj) { if (obj instanceof Jedis) { final Jedis jedis = (Jedis) obj; try { return jedis.isConnected() && jedis.ping().equals("PONG"); } catch (final Exception e) { return false; } } else { return false; } } } }
JedisPoolConfig继承了GenericObjectPool.Config,用于指定一些线程池初始化参数。
package redis.clients.jedis; ? import org.apache.commons.pool.impl.GenericObjectPool.Config; ? /** * Subclass of org.apache.commons.pool.impl.GenericObjectPool.Config that * includes getters/setters so it can be more easily configured by Spring and * other IoC frameworks. * * Spring example: * * * * * * * For information on parameters refer to: * * http://commons.apache.org/pool/apidocs/org/apache/commons/pool/impl/ * GenericObjectPool.html */ public class JedisPoolConfig extends Config { public JedisPoolConfig() { // defaults to make your life with connection pool easier :) setTestWhileIdle(true); setMinEvictableIdleTimeMillis(60000); setTimeBetweenEvictionRunsMillis(30000); setNumTestsPerEvictionRun(-1); } ? public int getMaxIdle() { return maxIdle; } ? public void setMaxIdle(int maxIdle) { this.maxIdle = maxIdle; } ? public int getMinIdle() { return minIdle; } ? public void setMinIdle(int minIdle) { this.minIdle = minIdle; } ? public int getMaxActive() { return maxActive; } ? public void setMaxActive(int maxActive) { this.maxActive = maxActive; } ? public long getMaxWait() { return maxWait; } ? public void setMaxWait(long maxWait) { this.maxWait = maxWait; } ? public byte getWhenExhaustedAction() { return whenExhaustedAction; } ? public void setWhenExhaustedAction(byte whenExhaustedAction) { this.whenExhaustedAction = whenExhaustedAction; } ? public boolean isTestOnBorrow() { return testOnBorrow; } ? public void setTestOnBorrow(boolean testOnBorrow) { this.testOnBorrow = testOnBorrow; } ? public boolean isTestOnReturn() { return testOnReturn; } ? public void setTestOnReturn(boolean testOnReturn) { this.testOnReturn = testOnReturn; } ? public boolean isTestWhileIdle() { return testWhileIdle; } ? public void setTestWhileIdle(boolean testWhileIdle) { this.testWhileIdle = testWhileIdle; } ? public long getTimeBetweenEvictionRunsMillis() { return timeBetweenEvictionRunsMillis; } ? public void setTimeBetweenEvictionRunsMillis( long timeBetweenEvictionRunsMillis) { this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis; } ? public int getNumTestsPerEvictionRun() { return numTestsPerEvictionRun; } ? public void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) { this.numTestsPerEvictionRun = numTestsPerEvictionRun; } ? public long getMinEvictableIdleTimeMillis() { return minEvictableIdleTimeMillis; } ? public void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) { this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis; } ? public long getSoftMinEvictableIdleTimeMillis() { return softMinEvictableIdleTimeMillis; } ? public void setSoftMinEvictableIdleTimeMillis( long softMinEvictableIdleTimeMillis) { this.softMinEvictableIdleTimeMillis = softMinEvictableIdleTimeMillis; } ? }

继续阅读


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

Notepad++7.3.1
Easy-to-use and free code editor

SublimeText3 Chinese version
Chinese version, very easy to use

Zend Studio 13.0.1
Powerful PHP integrated development environment

Dreamweaver CS6
Visual web development tools

SublimeText3 Mac version
God-level code editing software (SublimeText3)

Hot Topics



CrystalDiskMark is a small HDD benchmark tool for hard drives that quickly measures sequential and random read/write speeds. Next, let the editor introduce CrystalDiskMark to you and how to use crystaldiskmark~ 1. Introduction to CrystalDiskMark CrystalDiskMark is a widely used disk performance testing tool used to evaluate the read and write speed and performance of mechanical hard drives and solid-state drives (SSD). Random I/O performance. It is a free Windows application and provides a user-friendly interface and various test modes to evaluate different aspects of hard drive performance and is widely used in hardware reviews

foobar2000 is a software that can listen to music resources at any time. It brings you all kinds of music with lossless sound quality. The enhanced version of the music player allows you to get a more comprehensive and comfortable music experience. Its design concept is to play the advanced audio on the computer The device is transplanted to mobile phones to provide a more convenient and efficient music playback experience. The interface design is simple, clear and easy to use. It adopts a minimalist design style without too many decorations and cumbersome operations to get started quickly. It also supports a variety of skins and Theme, personalize settings according to your own preferences, and create an exclusive music player that supports the playback of multiple audio formats. It also supports the audio gain function to adjust the volume according to your own hearing conditions to avoid hearing damage caused by excessive volume. Next, let me help you

StableDiffusion3’s paper is finally here! This model was released two weeks ago and uses the same DiT (DiffusionTransformer) architecture as Sora. It caused quite a stir once it was released. Compared with the previous version, the quality of the images generated by StableDiffusion3 has been significantly improved. It now supports multi-theme prompts, and the text writing effect has also been improved, and garbled characters no longer appear. StabilityAI pointed out that StableDiffusion3 is a series of models with parameter sizes ranging from 800M to 8B. This parameter range means that the model can be run directly on many portable devices, significantly reducing the use of AI

NetEase Mailbox, as an email address widely used by Chinese netizens, has always won the trust of users with its stable and efficient services. NetEase Mailbox Master is an email software specially created for mobile phone users. It greatly simplifies the process of sending and receiving emails and makes our email processing more convenient. So how to use NetEase Mailbox Master, and what specific functions it has. Below, the editor of this site will give you a detailed introduction, hoping to help you! First, you can search and download the NetEase Mailbox Master app in the mobile app store. Search for "NetEase Mailbox Master" in App Store or Baidu Mobile Assistant, and then follow the prompts to install it. After the download and installation is completed, we open the NetEase email account and log in. The login interface is as shown below

Cloud storage has become an indispensable part of our daily life and work nowadays. As one of the leading cloud storage services in China, Baidu Netdisk has won the favor of a large number of users with its powerful storage functions, efficient transmission speed and convenient operation experience. And whether you want to back up important files, share information, watch videos online, or listen to music, Baidu Cloud Disk can meet your needs. However, many users may not understand the specific use method of Baidu Netdisk app, so this tutorial will introduce in detail how to use Baidu Netdisk app. Users who are still confused can follow this article to learn more. ! How to use Baidu Cloud Network Disk: 1. Installation First, when downloading and installing Baidu Cloud software, please select the custom installation option.

MetaMask (also called Little Fox Wallet in Chinese) is a free and well-received encryption wallet software. Currently, BTCC supports binding to the MetaMask wallet. After binding, you can use the MetaMask wallet to quickly log in, store value, buy coins, etc., and you can also get 20 USDT trial bonus for the first time binding. In the BTCCMetaMask wallet tutorial, we will introduce in detail how to register and use MetaMask, and how to bind and use the Little Fox wallet in BTCC. What is MetaMask wallet? With over 30 million users, MetaMask Little Fox Wallet is one of the most popular cryptocurrency wallets today. It is free to use and can be installed on the network as an extension

This paper explores the problem of accurately detecting objects from different viewing angles (such as perspective and bird's-eye view) in autonomous driving, especially how to effectively transform features from perspective (PV) to bird's-eye view (BEV) space. Transformation is implemented via the Visual Transformation (VT) module. Existing methods are broadly divided into two strategies: 2D to 3D and 3D to 2D conversion. 2D-to-3D methods improve dense 2D features by predicting depth probabilities, but the inherent uncertainty of depth predictions, especially in distant regions, may introduce inaccuracies. While 3D to 2D methods usually use 3D queries to sample 2D features and learn the attention weights of the correspondence between 3D and 2D features through a Transformer, which increases the computational and deployment time.

Apple rolled out the iOS 17.4 update on Tuesday, bringing a slew of new features and fixes to iPhones. The update includes new emojis, and EU users will also be able to download them from other app stores. In addition, the update also strengthens the control of iPhone security and introduces more "Stolen Device Protection" setting options to provide users with more choices and protection. "iOS17.3 introduces the "Stolen Device Protection" function for the first time, adding extra security to users' sensitive information. When the user is away from home and other familiar places, this function requires the user to enter biometric information for the first time, and after one hour You must enter information again to access and change certain data, such as changing your Apple ID password or turning off stolen device protection.
