日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

简单轻量级池实现

發(fā)布時(shí)間:2023/12/3 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 简单轻量级池实现 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

對(duì)象池是包含指定數(shù)量的對(duì)象的容器。 從池中獲取對(duì)象時(shí),在將對(duì)象放回之前,該對(duì)象在池中不可用。 池中的對(duì)象具有生命周期:創(chuàng)建,驗(yàn)證,銷毀等。池有助于更好地管理可用資源。 有許多使用示例。 特別是在應(yīng)用程序服務(wù)器中,有數(shù)據(jù)源池,線程池等。在以下情況下應(yīng)使用池:

  • 高頻使用相同的物體
  • 對(duì)象很大,消耗很多內(nèi)存
  • 對(duì)象需要很多時(shí)間進(jìn)行初始化
  • 對(duì)象使用大量的IO操作(流,套接字,數(shù)據(jù)庫(kù)等)
  • 對(duì)象不是線程安全的

當(dāng)我為我的一個(gè)Java項(xiàng)目尋找一個(gè)池實(shí)現(xiàn)時(shí),我發(fā)現(xiàn)許多人都引用了Apache Commons Pool 。 Apache Commons Pool提供了一個(gè)對(duì)象池API。 有接口ObjectPool,ObjectPoolFactory,PoolableObjectFactory和許多實(shí)現(xiàn)。 池提供添加,獲取,刪除和返回對(duì)象的方法addObject,借款對(duì)象,invalidateObject,returnObject。 PoolableObjectFactory定義池中對(duì)象的行為,并為池的操作提供各種回調(diào)。

在仔細(xì)研究實(shí)現(xiàn)細(xì)節(jié)之后,我發(fā)現(xiàn)Apache Commons Pool不是一個(gè)輕量級(jí)的實(shí)現(xiàn),這對(duì)我來說是一個(gè)開銷。 此外,它對(duì)許多方法都使用了舊的Java關(guān)鍵字sync,因此不建議使用這些方法。 Java 5引入了用于Java并發(fā)(多線程)的Executor框架。 此處最好使用Executor框架。 我決定實(shí)現(xiàn)一個(gè)簡(jiǎn)單且輕量級(jí)的池,我想在這里介紹它。 它只是一個(gè)Java類。 我認(rèn)為如果您不需要回調(diào)和其他高級(jí)功能就足夠了。 我在GitHub上創(chuàng)建了一個(gè)項(xiàng)目easy-pool 。

池實(shí)現(xiàn)基于java.util.concurrent包中的ConcurrentLinkedQueue。 ConcurrentLinkedQueue是基于鏈接節(jié)點(diǎn)的線程安全隊(duì)列。 該隊(duì)列按照FIFO原理(先進(jìn)先出)對(duì)元素進(jìn)行排序。 我對(duì)通用池的實(shí)現(xiàn)如下所示

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提供了兩個(gè)主要方法:roweObject從池中獲取下一個(gè)空閑對(duì)象,returnObject將借入的對(duì)象返回池中。 如果池中不包含任何對(duì)象,則將創(chuàng)建一個(gè)新對(duì)象,并將其交還給借方方法的調(diào)用者。 對(duì)象創(chuàng)建在方法createObject中進(jìn)行。 任何擴(kuò)展抽象類ObjectPool的類都只需實(shí)現(xiàn)此方法,即可使用該池。 如您所見,我還利用java.util.concurrent包中的ScheduledExecutorService。 這有什么用? 您可以指定池中駐留的最小和最大對(duì)象數(shù)。 ScheduledExecutorService在單獨(dú)的線程中啟動(dòng)特殊任務(wù),并在指定的時(shí)間(參數(shù)validationInterval)中觀察定期對(duì)象池中的最小和最大數(shù)量。 當(dāng)對(duì)象數(shù)小于最小值時(shí),將創(chuàng)建丟失的實(shí)例。 當(dāng)對(duì)象數(shù)大于最大值時(shí),將刪除太多實(shí)例。 有時(shí)這對(duì)于平衡池中的內(nèi)存消耗對(duì)象等很有用。

讓我們實(shí)現(xiàn)測(cè)試類以顯示對(duì)具體池的使用。 首先,我們需要一個(gè)類來表示池中的對(duì)象,該類模擬耗時(shí)的過程。 稱為ExportingProcess的此類需要一些時(shí)間才能實(shí)例化。

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;} }

第二類實(shí)現(xiàn)Runnable接口并模擬線程執(zhí)行的某些任務(wù)。 在run方法中,我們借用一個(gè)ExportingProcess實(shí)例,然后將其返回到池中。

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");} }

現(xiàn)在,在JUnit類TestObjectPool中,我們創(chuàng)建一個(gè)ExportingProcess類型的對(duì)象池。 這是通過新的ObjectPool <ExportingProcess>(4,10,5)發(fā)生的。 參數(shù)在下面的注釋中描述。

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();}} }

測(cè)試輸出看起來像

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

可以看出,訪問該池的第一個(gè)線程創(chuàng)建了駐留在該池中的最少對(duì)象。 多次運(yùn)行該測(cè)試類,我們可以發(fā)現(xiàn)有時(shí)4個(gè)對(duì)象相互借用,并且將在池中創(chuàng)建一個(gè)新的5.對(duì)象。 所有測(cè)試類均可在GitHub中獲得 。

參考:來自JCG合作伙伴 Oleg Varaksin的簡(jiǎn)單輕量級(jí)池實(shí)現(xiàn) ,位于“ 軟件開發(fā)思想”博客上。

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

總結(jié)

以上是生活随笔為你收集整理的简单轻量级池实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。