いくつかのオブジェクトをプールして共有しようとしていますが、スレッドでブロックされていることに気付きました。私はJavaに少し慣れていないので、これが私の経験不足の問題なのか、プールに固有の問題なのかわかりません。問題を再現するコードを次に示します (10 個のスレッドを作成し、20 個のオブジェクトを共有します。これを長いループで実行して、ブロッキングをキャッチできるようにします)。それをプロファイリングすると (スレッド ビューで Java visualvm または yourkit)、borrowObject がスレッドをブロックしているように見えることがわかります。問題は、これは正常な動作ですか、それとも私が何か間違ったことをしているのでしょうか?
私は完全に間違っている可能性がありますが、プールの新しいオブジェクトを作成/破棄するときにブロックされる可能性があることをどこかで読みました。オブジェクトの寿命を延ばす方法と、スレッドがアイドル状態でない場合に破棄/作成する必要がある理由がわかりませんか?
次に例を示します。
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.apache.commons.pool.BasePoolableObjectFactory;
import org.apache.commons.pool.ObjectPool;
import org.apache.commons.pool.impl.GenericObjectPool;
public class main{
public static void main(String[] a){
ObjectPool<Foo> fpool = new GenericObjectPool<Foo>(new FooPoolableObjectFactory(), 20);
ExecutorService tpool = Executors.newFixedThreadPool(10);
for(int i = 0; i < 900000000; ++i){
tpool.submit(new FooWorker(fpool));
}
}
}
class Foo{
private static int pk = 0;
private int count = 0;
public final int id;
public Foo(){
id = pk++;
}
public int increment(){
return ++count;
}
}
class FooWorker implements Runnable{
private ObjectPool<Foo> fpool;
public FooWorker(ObjectPool<Foo> fpool){
this.fpool = fpool;
}
@Override
public void run(){
Foo foo = null;
try{
foo = fpool.borrowObject();
//System.out.println(foo.id + ": " + foo.increment());
}
catch(Exception e){
e.printStackTrace();
}
finally{
// This is done in a finally block to ensure the object is returned to the pool
if(foo != null){
try{
fpool.returnObject(foo);
}
catch(Exception e){
e.printStackTrace();
}
}
}
}
}
class FooPoolableObjectFactory extends BasePoolableObjectFactory<Foo>{
@Override
public Foo makeObject() throws Exception{
return new Foo();
}
}
/*
Example output:
1: 1
0: 1
2: 1
3: 1
2: 2
0: 2
2: 3
0: 3
1: 2
3: 2
The number on the left is the id of the foo object being used.
The number on the right is the value of the foo object.
Notice how the foos are being reused.
*/