js 实现轻量ps_简单轻量的池实现

js 实现轻量ps

对象池是包含指定数量的对象的容器。 从池中获取对象时,在将对象放回之前,该对象在池中不可用。 池中的对象具有生命周期:创建,验证,销毁等。池有助于更好地管理可用资源。 有许多使用示例。 特别是在应用程序服务器中,有数据源池,线程池等。在以下情况下应使用池:

  • 高频使用相同的物体
  • 对象很大,消耗很多内存
  • 对象需要很多时间进行初始化
  • 对象使用大量的IO操作(流,套接字,数据库等)
  • 对象不是线程安全的

当我为我的一个Java项目寻找一个池实现时,我发现许多人都引用了Apache Commons Pool 。 Apache Commons Pool提供了一个对象池API。 有接口ObjectPool,ObjectPoolFactory,PoolableObjectFactory和许多实现。 池提供方法addObject,借款对象,invalidateObject,returnObject来添加,获取,移除和返回对象。 PoolableObjectFactory定义池中对象的行为,并为池的操作提供各种回调。

在仔细研究实现细节之后,我发现Apache Commons Pool不是轻量级的实现,这对我来说是一个开销。 此外,它对许多方法都使用了旧的Java关键字sync,因此不建议使用许多方法。 Java 5引入了用于Java并发(多线程)的Executor框架。 此处最好使用Executor框架。 我决定实现一个简单且轻量级的池,我想在这里介绍它。 它只是一个Java类。 我认为如果您不需要回调和其他高级功能就足够了。 我在GitHub上创建了一个项目easy-pool 。

池实现基于java.util.concurrent包中的ConcurrentLinkedQueue。 ConcurrentLinkedQueue是基于链接节点的线程安全队列。 该队列按照FIFO原理(先进先出)对元素进行排序。 我对通用池的实现如下所示

import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;public abstract class ObjectPool<T>
{private ConcurrentLinkedQueue<T> pool;private ScheduledExecutorService executorService;/*** Creates the pool.** @param minIdle minimum number of objects residing in the pool*/public ObjectPool(final int minIdle) {// initialize poolinitialize(minIdle);}/*** Creates the pool.** @param minIdle            minimum number of objects residing in the pool* @param maxIdle            maximum number of objects residing in the pool* @param validationInterval time in seconds for periodical checking of minIdle / maxIdle conditions in a separate thread.*                           When the number of objects is less than minIdle, missing instances will be created.*                           When the number of objects is greater than maxIdle, too many instances will be removed.*/public ObjectPool(final int minIdle, final int maxIdle, final long validationInterval) {// initialize poolinitialize(minIdle);// check pool conditions in a separate threadexecutorService = Executors.newSingleThreadScheduledExecutor();executorService.scheduleWithFixedDelay(new Runnable(){@Overridepublic void run() {int size = pool.size();if (size < minIdle) {int sizeToBeAdded = minIdle - size;for (int i = 0; i < sizeToBeAdded; i++) {pool.add(createObject());}} else if (size > maxIdle) {int sizeToBeRemoved = size - maxIdle;for (int i = 0; i < sizeToBeRemoved; i++) {pool.poll();}}}}, validationInterval, validationInterval, TimeUnit.SECONDS);}/*** Gets the next free object from the pool. If the pool doesn't contain any objects,* a new object will be created and given to the caller of this method back.** @return T borrowed object*/public T borrowObject() {T object;if ((object = pool.poll()) == null) {object = createObject();}return object;}/*** Returns object back to the pool.** @param object object to be returned*/public void returnObject(T object) {if (object == null) {return;}this.pool.offer(object);}/*** Shutdown this pool.*/public void shutdown() {if (executorService != null) {executorService.shutdown();}}/*** Creates a new object.** @return T new object*/protected abstract T createObject();private void initialize(final int minIdle) {pool = new ConcurrentLinkedQueue<T>();for (int i = 0; i < minIdle; i++) {pool.add(createObject());}}
}

抽象类ObjectPool提供了两个主要方法:roweObject从池中获取下一个空闲对象,returnObject将借入的对象返回池中。 如果池中不包含任何对象,则将创建一个新对象,并将其交还给借阅方法的调用者。 对象创建在方法createObject中进行。 任何扩展抽象类ObjectPool的类都只需实现此方法,即可使用该池。 如您所见,我还利用java.util.concurrent包中的ScheduledExecutorService。 这有什么用? 您可以指定池中驻留的最小和最大对象数。 ScheduledExecutorService在单独的线程中启动特殊任务,并在指定时间(参数validationInterval)中观察定期对象池中的最小和最大数量。 当对象数小于最小值时,将创建丢失的实例。 当对象数大于最大值时,将删除太多实例。 有时这对于平衡池中的内存消耗对象以及更多对象很有用。

让我们实现测试类以显示对具体池的使用。 首先,我们需要一个表示池中对象的类,该类模拟耗时的过程。 称为ExportingProcess的此类需要一些时间才能实例化。

public class ExportingProcess {private String location;private long processNo = 0;public ExportingProcess(String location, long processNo) {this.location = location;this.processNo = processNo;// doing some time expensive calls / tasks// ...// for-loop is just for simulationfor (int i = 0; i < Integer.MAX_VALUE; i++) {}System.out.println("Object with process no. " + processNo + " was created");}public String getLocation() {return location;}public long getProcessNo() {return processNo;}
}

第二类实现Runnable接口并模拟线程执行的某些任务。 在run方法中,我们借用了ExportingProcess的一个实例,稍后将其返回到池中。

public class ExportingTask implements Runnable {private ObjectPool<ExportingProcess> pool;private int threadNo;public ExportingTask(ObjectPool<ExportingProcess> pool, int threadNo) {this.pool = pool;this.threadNo = threadNo;}public void run() {// get an object from the poolExportingProcess exportingProcess = pool.borrowObject();System.out.println("Thread " + threadNo + ": Object with process no. " + exportingProcess.getProcessNo() + " was borrowed");// do something// ...// for-loop is just for simulationfor (int i = 0; i < 100000; i++) {}// return ExportingProcess instance back to the poolpool.returnObject(exportingProcess);System.out.println("Thread " + threadNo + ": Object with process no. " + exportingProcess.getProcessNo() + " was returned");}
}

现在,在JUnit类TestObjectPool中,我们创建一个ExportingProcess类型的对象池。 这是通过新的ObjectPool <ExportingProcess>(4,10,5)发生的。 参数在下面的注释中描述。

import org.junit.After;
import org.junit.Before;
import org.junit.Test;import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;public class TestObjectPool
{private ObjectPool<ExportingProcess> pool;private AtomicLong processNo = new AtomicLong(0);@Beforepublic void setUp() {// Create a pool of objects of type ExportingProcess. Parameters:// 1) Minimum number of special ExportingProcess instances residing in the pool = 4// 2) Maximum number of special ExportingProcess instances residing in the pool = 10// 3) Time in seconds for periodical checking of minIdle / maxIdle conditions in a separate thread = 5.//    When the number of ExportingProcess instances is less than minIdle, missing instances will be created.//    When the number of ExportingProcess instances is greater than maxIdle, too many instances will be removed.//    If the validation interval is negative, no periodical checking of minIdle / maxIdle conditions//    in a separate thread take place. These boundaries are ignored then.pool = new ObjectPool<ExportingProcess>(4, 10, 5){protected ExportingProcess createObject() {// create a test object which takes some time for creationreturn new ExportingProcess("/home/temp/", processNo.incrementAndGet());}};}@Afterpublic void tearDown() {pool.shutdown();}@Testpublic void testObjectPool() {ExecutorService executor = Executors.newFixedThreadPool(8);// execute 8 tasks in separate threadsexecutor.execute(new ExportingTask(pool, 1));executor.execute(new ExportingTask(pool, 2));executor.execute(new ExportingTask(pool, 3));executor.execute(new ExportingTask(pool, 4));executor.execute(new ExportingTask(pool, 5));executor.execute(new ExportingTask(pool, 6));executor.execute(new ExportingTask(pool, 7));executor.execute(new ExportingTask(pool, 8));executor.shutdown();try {executor.awaitTermination(30, TimeUnit.SECONDS);} catch (InterruptedException e) {e.printStackTrace();}}
}

测试输出看起来像

Object with process no. 1 was created
Object with process no. 2 was created
Object with process no. 3 was created
Object with process no. 4 was created
Thread 2: Object with process no. 2 was borrowed
Thread 1: Object with process no. 1 was borrowed
Thread 2: Object with process no. 2 was returned
Thread 3: Object with process no. 3 was borrowed
Thread 4: Object with process no. 4 was borrowed
Thread 1: Object with process no. 1 was returned
Thread 4: Object with process no. 4 was returned
Thread 8: Object with process no. 4 was borrowed
Thread 5: Object with process no. 1 was borrowed
Thread 7: Object with process no. 3 was borrowed
Thread 3: Object with process no. 3 was returned
Thread 6: Object with process no. 2 was borrowed
Thread 7: Object with process no. 3 was returned
Thread 5: Object with process no. 1 was returned
Thread 8: Object with process no. 4 was returned
Thread 6: Object with process no. 2 was returned

可以看出,访问该池的第一个线程创建了驻留在池中的最少对象。 多次运行该测试类,我们会发现有时4个对象相互借用,并且会在池中创建一个新的5.对象。 所有测试类均可在GitHub中获得 。

参考:来自JCG合作伙伴 Oleg Varaksin的简单轻量级池实现 ,位于“ 软件开发思想”博客上。

翻译自: https://www.javacodegeeks.com/2013/08/simple-and-lightweight-pool-implementation.html

js 实现轻量ps

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/346987.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【MFC系列-第14天】MFC核心类库的成员介绍(记事本快捷键)

14.1 对话框快捷键的设置和加载 a) 插入一个新的Accelerator到资源里&#xff0c;把加速键和对应的响应控件(如一个按钮)关联 b) 在对话框头文件中声明 HACCEL m_hAccel;c) 在对话框的构造函数里初始化m_hAccel m_hAccel ::LoadAccelerators(AfxGetInstanceHandle(),MAKEI…

【MFC系列-第15天】关联变量的概念与用法

15.1 权限管理对话框的信息录入与保存 15.2 控件型关联变量&#xff1a; FromHandle和DeleteTempMap管理成员对象表&#xff0c;前者由HWND获取CWnd*&#xff0c;后者进行删除。 BOOL Attach( HWND hWndNew ); //关联 HWND Detach( ); //解除关联 BOOL SubclassWindow( HWND…

【MFC系列-第16天】企业信息管理软件开发

常见的两种类和类之间相互调用的方法。 16.1 用户权限信息在不同对话框之间共享 ①在CWokerApp类中定义变量&#xff1a; class CWorkerApp : public CWinApp { public:CWorkerApp();SAdmin m_admin;//登录信息 // 重写 public:virtual BOOL InitInstance(); // 实现DECLARE…

java微妙_编码Java时的10个微妙的最佳实践

java微妙这是10条最佳实践的列表&#xff0c;这些最佳实践比您的平均Josh Bloch有效Java规则要微妙得多。 尽管Josh Bloch的列表很容易学习&#xff0c;并且涉及日常情况&#xff0c;但此处的列表包含了涉及API / SPI设计的较不常见的情况&#xff0c;尽管这些情况可能会产生很…

【MFC系列-第17天】企业信息管理软件开发

关注公号【逆向通信猿】更精彩&#xff01;&#xff01;&#xff01; 17.1 数值型关联变量&#xff1a; a)在MFC中有部分控件支持数值型关联变量&#xff1a; 编辑控件、下拉控件、单选按钮、复选框以及日期控件&#xff1b; b)在类向导中为控件建立关联变量时&#xff0c;选…

GraphQL在Wildfly群上

“ GraphQL是API的查询语言&#xff0c;是用于使用现有数据完成这些查询的运行时。 GraphQL为您的API中的数据提供了一个完整且易于理解的描述&#xff0c;使客户能够准确地询问他们所需的内容&#xff0c;仅此而已&#xff0c;使随着时间的推移更容易开发API并启用强大的开发人…

【MFC系列-第18天】企业信息管理软件开发

关注公号【逆向通信猿】更精彩&#xff01;&#xff01;&#xff01; CWnd类中常用的成员函数 函数名称含义static CWnd* PASCAL GetActiveWindow( )&#xff08;进程内的&#xff09;获取活动窗口CWnd* SetActiveWindow( )&#xff08;进程内的&#xff09;将一个窗口设置为…

【MFC系列-第19天】初步认识GDI绘图技术

WM_PAINT消息测试 调试输出字符串 OutputDebugSting(_T(“WM_PAINT-OnPaint\n”));1、WM_PAINT&#xff1a;功能和发生时间 2、BeginPaint和EndPaint必须成对使用。 a)BeginPaint返回的DC句柄&#xff0c;是基于关联的窗口客户区坐标系绘图 b)MFC把这两个函数封装为一个类…

javafx 示例_示例介绍:JavaFX 8打印

javafx 示例我有一段时间没有写博客了&#xff0c;我想与其他人分享有关JavaFX的所有信息&#xff08;我的日常工作和家庭可能是借口&#xff09;。 对于那些对此博客不熟悉的人 &#xff0c;我是JavaFX 2 Introduction by Example&#xff08;JIBE&#xff09;的作者&#xff…

【MFC系列-第20天】CDC绘图类成员介绍

20.1 三大坐标系&#xff1a;屏幕、客户区和非客户区 20.2 三大派生类&#xff1a; a)CPaintDC(客户区标准绘图&#xff09;,内部封装函数是&#xff1a;BeginPaint和EndPaint b)CClientDC&#xff08;客户区非标准绘图&#xff09;,内部是&#xff1a;::GetDC和ReleaseDC …

Spring Data JPA教程

在Java类或对象与关系数据库之间管理数据是一项非常繁琐且棘手的任务。 DAO层通常包含许多样板代码&#xff0c;应简化这些样板代码&#xff0c;以减少代码行数并使代码可重复使用。 在本教程中&#xff0c;我们将讨论Spring数据的JPA实现。 1.简介 1.1什么是JPA&#xff1f;…

【MFC系列-第21天】GDI算法实战——过渡色

21.1 Caption过渡色实现 // 方法一 void CCaptionDlg::DrawColorTitle(CRect rect, COLORREF col1, COLORREF col2,CDC* pDC) {int cx rect.Width();int red GetRValue(col2) - GetRValue(col1);int green GetGValue(col2) - GetGValue(col1);int blue GetBValue(col2) -…

在Spring MVC中处理域对象

最近&#xff0c;我惊讶于一个代码库在其所有域实体中都具有公共默认构造函数&#xff08;即零参数构造函数&#xff09;&#xff0c;并且所有字段都具有getter和setter。 当我深入研究时&#xff0c;我发现域实体之所以如此&#xff0c;主要是因为该团队认为Web / MVC框架需要…

【有限域元素加法和乘法】有限域元素加法和乘法的原理及MATLAB实现

关注公号【逆向通信猿】更精彩!!! 有限域 仍然以 r = 4 r=4 r=4,

使用storm 实时计算_使用Storm进行可扩展的实时状态更新

使用storm 实时计算在本文中&#xff0c;我将说明如何借助Storm框架以可扩展且无锁定的方式在数据库中维护实时事件驱动流程的当前状态。 Storm是基于事件的数据处理引擎。 它的模型依赖于基本原语&#xff0c;例如事件转换&#xff0c;过滤&#xff0c;聚合……&#xff0c;我…

【MFC系列-第22天】GDI算法实战——过渡色

关注公号【逆向通信猿】更精彩&#xff01;&#xff01;&#xff01; 第22天 GDI算法实战 CDC(HDC)绘图类&#xff1a; 五大GDI对象类&#xff1a;CPen&#xff0c;CBrush&#xff0c;CFont&#xff0c;CBitmap&#xff0c;CRgn 22.1 走马灯 设置定时器 SetTimer(1, 20, N…

无服务器:不费吹灰之力!

几年前&#xff0c; 集装箱横扫开发人员&#xff0c;而开发人员的土地就像6级飓风一样 。 码头工人 Rkt 。 其他 。 Docker Swarm 。 K8s 。 OpenShift 。 现在&#xff0c;我们实际上处于震中&#xff0c;但是当我们瞥见地平线时&#xff0c;我们看到另一个人来了&#x…

【MFC系列-第23天】CMemoryDC的封装过程

CDC(HDC)绘图类&#xff1a; 五大GDI对象类&#xff1a;CPen&#xff0c;CBrush&#xff0c;CFont&#xff0c;CBitmap&#xff0c;CRgn 23.1 LoadImage API HANDLE LoadImage(HINSTANCE hinst,LPCTSTR lpszName, UINT uType, int cxDesired,int cyDesired,UINT fuLoad );uT…

JDK 8与JDK 10:三元/拆箱的区别

最近的Nicolai Parlog &#xff08; nipafx &#xff09; 鸣叫引起了我的注意&#xff0c;因为它引用了关于JDK 8和JDK 10之间行为更改的有趣StackOverflow讨论 &#xff0c;并询问“为什么&#xff1f;” SerCe 在StackOverflow线程上引用的问题最终归结为在JDK 8和JDK 10之间…

【多元域乘法】多项式乘法电路原理及MATLAB详解

关注公号【逆向通信猿】更精彩!!! 关于二元域上的两个元素的乘法、多项式除法,在之前的博客 【有限域除法】二元多项式除法电路原理及MATLAB详解 子程序:sub_poly_div.m 【有限域元素加法和乘法】有限域元素加法和乘法的原理及MATLAB实现 子程序:sub_gf_add.m、sub_gf_…