kagamihogeの日記

kagamihogeの日記です。

Apache Commons Poolのサンプル

object poolを自力で実装する機会は余りないが、Apache Commons Poolが便利な局面があったのでその使い方をメモしておく。

plugins {
    id 'java'
    id 'org.springframework.boot' version '3.0.0'
    id 'io.spring.dependency-management' version '1.1.0'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
}

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    compileOnly 'org.projectlombok:lombok'
    developmentOnly 'org.springframework.boot:spring-boot-devtools'
    annotationProcessor 'org.projectlombok:lombok'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    implementation 'org.apache.commons:commons-pool2'
    implementation 'org.apache.commons:commons-lang3'
}

tasks.named('test') {
    useJUnitPlatform()
}

spring-bootと直接の関係は無いけど現実的には一緒に使うだろうし、versionも省略出来るので、こうしている。commons-lang3も無関係だけど、説明用のランダム文字列生成のために使う。

import java.util.NoSuchElementException;

import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.pool2.BasePooledObjectFactory;
import org.apache.commons.pool2.ObjectPool;
import org.apache.commons.pool2.PooledObject;
import org.apache.commons.pool2.PooledObjectFactory;
import org.apache.commons.pool2.impl.DefaultPooledObject;
import org.apache.commons.pool2.impl.GenericObjectPool;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;

public class CommonsPool2Sample {

  public static void main(String[] args) throws NoSuchElementException, IllegalStateException, Exception {
    PooledObjectFactory<String> factory = new BasePooledObjectFactory<String>() {

      @Override
      public String create() throws Exception {
        String created = RandomStringUtils.randomAlphanumeric(5);
        System.out.println("created:" + created);
        return created;
      }

      @Override
      public PooledObject<String> wrap(String obj) {
        return new DefaultPooledObject<>(obj);
      }
    };

    GenericObjectPoolConfig<String> config = new GenericObjectPoolConfig<>();
    config.setMaxTotal(3);

    try (ObjectPool<String> pool = new GenericObjectPool<>(factory, config)) {
      pool.addObjects(config.getMaxTotal());

      String a1 = pool.borrowObject();
      String a2 = pool.borrowObject();
      String a3 = pool.borrowObject();
      System.out.println(a1 + " " + a2 + " " + a3);

      pool.returnObject(a1);

      System.out.println(pool.borrowObject());
      pool.borrowObject();
    }
  }
}

実用性ゼロなObjectPoolの動作確認するためだけのコードである。実行すると以下の出力をして無限待機する。

created:HpT2W
created:Yz1T5
created:oVjKr
oVjKr Yz1T5 HpT2W
oVjKr

プールの最大数3で4個目を取得しようとするので無限ブロックする。同時実行の要件次第で setMaxWait とかを設定する。

addObjectsはあらかじめプールにオブジェクト生成を命じるもの。これも要件次第で事前初期化か遅延かを選ぶ感じ。

createjavadocThis method must support concurrent, multi-threadedactivation.にある通り、マルチスレッド環境下では同期化の考慮が必要。