Java并发对象池?
问题描述:
我试图将外部非线程安全的库集成到我的Web项目中;我发现为每个客户端线程创建此对象的实例太昂贵了。Java并发对象池?
因此,我想创建一个具有以下属性的对象池。
- 动态对象创建,动态创建池中的对象,而不是在构造函数中创建它们。池最初是空的,当客户端线程获取资源对象时,池可以按需创建新资源。一旦创建的对象的数量达到池的大小,那么新的客户端线程将被阻塞,并等待其他线程回收资源。
- 池应该是公平的,并且公平确保询问的第一个线程是第一个获取的线程;否则有些线程可能会永远等待。
我该怎么办?如果有一个实例,我会很感激。
答
并发对象池可以通过阻塞队列中的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();
}
}
}
链接不可用 – 2014-12-16 08:49:25
我更新了链接。 – 2014-12-17 19:36:47
非常感谢。它现在有效! – 2014-12-18 07:33:52