Java并发对象池?

编程入门 行业动态 更新时间:2024-10-11 09:22:32
本文介绍了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.

  • 动态对象创建,池中的对象是动态创建的,而不是在构造函数中创建。池最初为空,并且当客户端线程获取资源对象时,池可以按需创建新的资源。一旦达到创建的对象的数量达到池的大小;那么新的客户端线程将被阻塞,并等待其他线程回收资源。
  • 池应该公平,公平性确保请求的第一个线程是获取的第一个线程;
  • 如何做到这一点?

    推荐答案

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

    This question and solution are summarized from www.dbtsai/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并发对象池?

    本文发布于:2023-08-04 21:44:58,感谢您对本站的认可!
    本文链接:https://www.elefans.com/category/jswz/34/1299877.html
    版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
    本文标签:对象   Java

    发布评论

    评论列表 (有 0 条评论)
    草根站长

    >www.elefans.com

    编程频道|电子爱好者 - 技术资讯及电子产品介绍!