我有一个必须在多个线程之间共享的对象列表。如何共享Java中并行处理的对象列表?
例如,我有一个5个离散对象和一个20个线程池。首先20个线程中的5个将开始工作,使其他线程处于WAIT状态。 5个线程将同时利用5个对象中的每一个。
如果任何线程完成,它应该释放该对象,以便第6个线程可以开始工作。
对于线程的并行处理我想我可以使用Executor池。但是如何在线程中共享对象列表?
我有一个必须在多个线程之间共享的对象列表。如何共享Java中并行处理的对象列表?
例如,我有一个5个离散对象和一个20个线程池。首先20个线程中的5个将开始工作,使其他线程处于WAIT状态。 5个线程将同时利用5个对象中的每一个。
如果任何线程完成,它应该释放该对象,以便第6个线程可以开始工作。
对于线程的并行处理我想我可以使用Executor池。但是如何在线程中共享对象列表?
我觉得你有你的线程模型是错误的。目前你想要share
这在并行环境中总是错误的。你应该做的是创建一个pipeline
。要做到这一点,你有几个选择。
使用(阻塞/并发)队列在线程之间传递对象。在这种情况下,管道的每个阶段都有固定数量的工作线程,这些工作线程始终在运行并共享队列。一方面你有producer
线程,当它们完成put()
对象到队列,然后consumer
线程take()
之一,并开始处理它。 (1)使用threadpool
充当队列。而不是在共享队列上执行put()
,而是对共享或专用线程池执行submit()/execute()
以将对象传递到管道的下一个阶段。这种方法的缺点是,现阶段必须知道提交任务的确切池,并知道如何创建要提交的runnable
。
PS:在我的答案我假设线程6执行不同于前面的5个线程的操作类型。如果这种假设不正确 - 解决方案(1)仍然是正确的,并且是前进的方向。
谢谢。有用。你是对的。每个线程将执行不同类型的操作。 –
我怀疑在JDK中有一个标准的实现,但是你可以根据自己的需求建立自己的对象池,或者可能看一个库, https://commons.apache.org/proper/commons-pool/
您可以定义要并行运行的线程数。例如,
ExecutorService executor = Executors.newFixedThreadPool(20);
然后,您可以编写for循环来处理对象列表。
for(Object obj: objList) {
Runnable thread = new MyThreadImpl(obj);
executor.execute(thread);
}
这应该工作,按您的
完全正常使用重入锁
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();
}
}
对我来说,你在说的是Object pool pattern。对象池是包含指定数量对象的容器。从池中取出对象时,在放回池之前,该对象在池中不可用。
池应在诸如使用:使用同一对象的
某些出版物不建议使用对象池,尤其是对于仅使用内存且不包含外部资源的对象。相关批评question。
取决于你为什么需要这种模式。这里是implementation in Java。
乘坐的BlockingQueue(https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/BlockingQueue.html),并把对象重新调整完毕后 – Gilfoyle
是6号线做与第五个对象不同的东西?如果只有5个对象,为什么还需要5个以上的线程?当你需要4倍的线程数时,肯定没有性能优势。 – Kayaman
是的。尽管它们具有相同的源代码,但所有20个线程都将具有不同的操作。操作将根据提供给源代码的输入而有所不同。正如** Gilfoy **和** Svetlin Zarev **所建议的那样,我正在使用一个现在完美工作的实现。感谢您的意见。 –