我有一个必须在多个线程之间共享的对象列表。
例如,我有5个离散对象和20个线程的池。 20个线程中的前5个将开始工作,其他线程处于WAIT状态。 5个线程将同时使用5个对象中的每一个。
如果任何线程完成,它应该释放该对象,以便第6个线程可以开始工作。
对于线程的并行处理,我认为我可以使用Executor池。但是如何在线程之间共享对象列表呢?
答案 0 :(得分:2)
我认为你的线程模型错了。目前,您希望share
在并行环境中始终存在错误。你应该做的是创建一个pipeline
。为此,您有几种选择。
使用(阻塞/并发)队列在线程之间传递对象。在这种情况下,管道的每个阶段都有固定数量的工作线程,这些工作线程始终在运行并共享队列。一方面,你有producer
个线程,当它们完成put()
对象到队列,然后一个consumer
线程take()
对象并开始处理它。
使用threadpool
作为(1)中的队列。您不必在共享队列上执行put()
,而是submit()/execute()
到共享或专用线程池,以将对象传递到管道的下一个阶段。这种方法的缺点是,当前阶段必须知道提交任务的确切池,以及知道如何创建要提交的runnable
。
PS:在我的回答中,我假设Thread-6执行的操作与前5个线程不同。如果这个假设不正确 - 解决方案(1)仍然是正确的,并且是前进的方向。
答案 1 :(得分:1)
您可以定义要并行运行的线程数。例如,
ExecutorService executor = Executors.newFixedThreadPool(20);
然后你可以写一个for循环来处理对象列表。
for(Object obj: objList) {
Runnable thread = new MyThreadImpl(obj);
executor.execute(thread);
}
根据你的
,这应该完全正常答案 2 :(得分:1)
在我看来,你在谈论Object pool pattern。对象池是包含指定数量对象的容器。当从池中取出一个对象时,它将在池中不可用,直到它被放回。
在以下情况下应使用池:
某些出版物不建议使用对象池,尤其是对于仅使用内存且不保留外部资源的对象。相关批评question。
取决于你为什么需要这种模式。这是implementation in Java。
答案 3 :(得分:0)
我怀疑JDK中是否有标准实现,但您可以根据您的要求构建自己的对象池,也可以查看库,例如https://commons.apache.org/proper/commons-pool/
答案 4 :(得分:0)
使用可重入锁
private static synchronized ReentrantLock getLock(Long id) {
if (!locks.containsKey(id)) {
locks.put(id, new ReentrantLock());
}
return locks.get(id);
}
private void lock(Long id) {
ReentrantLock lock = getLock(id);
lock.lock();
}
private void unlock(Long id) {
ReentrantLock lock = getLock(id);
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}