Java的并发对象池?(Java Concurrent Object Pool?)

2019-07-20 11:15发布

我试图外部非线程安全的库集成到我的web项目; 我发现它太昂贵,为每一个客户线程创建该对象的实例。

其结果是,我想创建它具有以下属性的对象池。

  1. 动态对象创建,池中的对象是动态创建的,而不是在构造函数创建它们。 池最初是空的,当一个客户端线程获取资源对象,池可以根据需要创建一个新的资源。 一旦创建的对象的数量都达到了池的大小; 那么新的客户端线程将被阻塞,并等待另一个线程来回收资源。
  2. 池应该是公正,公平性保证,要求第一个线程是第一个线程获得; 否则有可能发生一些线程只会永远等待。

我该怎么做? 如果有一个工作的例子,我会升值。

Answer 1:

这个问题和解决方案是从总结https://www.dbtsai.com/blog/2013/java-concurrent-dynamic-object-pool-for-non-thread-safe-objects-using-blocking-queue/

并发对象池可以通过使用Java并发包阻塞队列建成,并ArrayBlockingQueue也支持我们要求公平性。 在此实现,我用的ReentrantLock来控制,如果我们可以在游泳池或不创建一个新的对象。 其结果是,在非动态的创建模式,即,在构造函数中创建的所有对象,这个锁将一直锁定; 在动态创建模式,每次的,可以只创建一个对象,因此,如果有另一个线程获取该对象时,它会得到pool.take(),这是阻止删除对象,并等待新的可用资源在队列中。

    public abstract class ResourcePool {
        private final BlockingQueue pool;
        private final ReentrantLock lock = new ReentrantLock();
        private int createdObjects = 0;
        private int size;
     
        protected ResourcePool(int size) {
            this(size, false);
        }
     
        protected ResourcePool(int size, Boolean dynamicCreation) {
            // Enable the fairness; otherwise, some threads
            // may wait forever.
            pool = new ArrayBlockingQueue<>(size, true);
            this.size = size;
            if (!dynamicCreation) {
                lock.lock();
            }
        }
     
        public Resource acquire() throws Exception {
            if (!lock.isLocked()) {
                if (lock.tryLock()) {
                    try {
                        ++createdObjects;
                        return createObject();
                    } finally {
                        if (createdObjects < size) lock.unlock();
                    }
                }
            }
            return pool.take();
        }
     
        public void recycle(Resource resource) throws Exception {
            // Will throws Exception when the queue is full,
            // but it should never happen.
            pool.add(resource);
        }
     
        public void createPool() {
            if (lock.isLocked()) {
                for (int i = 0; i < size; ++i) {
                    pool.add(createObject());
                    createdObjects++;
                }
            }
        }
     
        protected abstract Resource createObject();
    }

在下面的例子中,有5个客户线程同时获取在资源池中的两个DataTimeFormat对象,这些客户端线程将在总做30次计算。

    class DataTimeFormatResourcePool extends ResourcePool<SimpleDateFormat> {
 
    DataTimeFormatResourcePool(int size, Boolean dynamicCreation) {
        super(size, dynamicCreation);
        createPool();
    }
 
    @Override
    protected SimpleDateFormat createObject() {
        return new SimpleDateFormat("yyyyMMdd");
    }
 
    public Date convert(String input) throws Exception {
        SimpleDateFormat format = acquire();
        try {
            return format.parse(input);
        } finally {
            recycle(format);
        }
    }
}
 
public class ResourcePoolExample {
    public static void main(String args[]) {
        final DataTimeFormatResourcePool pool = new DataTimeFormatResourcePool(2, true);
 
        Callable<Date> task = new Callable<Date>() {
            @Override
            public Date call() throws Exception {
                return pool.convert("20130224");
            }
        };
 
        ExecutorService exec = Executors.newFixedThreadPool(5);
        List<Future<Date>> results = new ArrayList<>();
 
        for (int i = 0; i < 30; i++) {
            results.add(exec.submit(task));
        }
        exec.shutdown();
        try {
            for (Future<Date> result : results) {
                System.out.println(result.get());
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}


文章来源: Java Concurrent Object Pool?