0

我正在尝试汇集一些对象并共享它们,但我注意到线程中的阻塞。我对 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.
*/
4

1 回答 1

1

不确定“阻塞”线程是什么意思(多个线程在同一个互斥体上等待?)。apache 池实现使用简单的同步,因此如果您的任务主要是在池中添加和删除对象所花费的时间,它就不是最并发的解决方案。假设您在借用和返回调用之间做了一些实际工作,您可能会看到更少的阻塞。

于 2012-05-04T14:16:34.153 回答