Java并发对象池?

问题描述:

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

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

  1. 动态对象创建,动态创建池中的对象,而不是在构造函数中创建它们。池最初是空的,当客户端线程获取资源对象时,池可以按需创建新资源。一旦创建的对象的数量达到池的大小,那么新的客户端线程将被阻塞,并等待其他线程回收资源。
  2. 池应该是公平的,并且公平确保询问的第一个线程是第一个获取的线程;否则有些线程可能会永远等待。

我该怎么办?如果有一个实例,我会很感激。

这个问题和解决方案是从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(); 
        } 
    } 
} 
+0

链接不可用 – 2014-12-16 08:49:25

+0

我更新了链接。 – 2014-12-17 19:36:47

+0

非常感谢。它现在有效! – 2014-12-18 07:33:52