Java并发对象池? [英] Java Concurrent Object Pool?

查看:254
本文介绍了Java并发对象池?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I tried to integrate an external non-thread-safe library to my web project; I found out that it's too expensive to create an instance of this object for each client thread.

因此,我想创建一个具有以下属性的对象池。

As a result, I would like to create an object pool which has the following property.


  1. 动态对象创建,池中的对象是动态创建的,而不是在构造函数中创建。池最初为空,并且当客户端线程获取资源对象时,池可以按需创建新的资源。一旦达到创建的对象的数量达到池的大小;那么新的客户端线程将被阻塞,并等待其他线程回收资源。

  2. 池应该公平,公平性确保请求的第一个线程是获取的第一个线程;

如何做到这一点?

推荐答案

此问题和解决方案摘自 https:// www。 dbtsai.com/blog/2013/java-concurrent-dynamic-object-pool-for-non-thread-safe-objects-using-blocking-queue/

This question and solution are summarized from https://www.dbtsai.com/blog/2013/java-concurrent-dynamic-object-pool-for-non-thread-safe-objects-using-blocking-queue/

并发对象池可以由Java并发包中的阻塞队列构建,ArrayBlockingQueue也支持我们需要的公平性。在这个实现中,我使用ReentrantLock来控制是否可以在池中创建一个新对象。结果,在非动态创建模式下,即在构造函数中创建所有对象,这个锁永远被锁定;在动态创建模式下,每次只能创建一个对象,因此如果有另一个线程获取此对象,它将从pool.take()获取对象,该对象被阻塞remove,并将等待一个新的可用资源在队列中。

The concurrent object pool can be built by the blocking queue in Java concurrent package, and ArrayBlockingQueue also supports fairness which we require. In this implementation, I use ReentrantLock to control if we can create a new object in the pool or not. As a result, in the non dynamic creation mode i.e., creating all the objects in the constructor, this lock will always be locked; in the dynamic creation mode, in each time, only one object can be created, so if there is another thread acquiring this object, it will get the object from pool.take() which is blocking remove, and will wait for a new available resource in the queue.

    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次计算。

In the following example, there are 5 client threads simultaneously acquiring two DataTimeFormat objects in resource pool, and those client threads will do 30 computations in total.

    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并发对象池?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆