2016-05-31 86 views
0

我有一个必须在多个线程之间共享的对象列表。如何共享Java中并行处理的对象列表?

例如,我有一个5个离散对象和一个20个线程池。首先20个线程中的5个将开始工作,使其他线程处于WAIT状态。 5个线程将​​同时利用5个对象中的每一个。

如果任何线程完成,它应该释放该对象,以便第6个线程可以开始工作。

对于线程的并行处理我想我可以使用Executor池。但是如何在线程中共享对象列表?

+0

乘坐的BlockingQueue(https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/BlockingQueue.html),并把对象重新调整完毕后 – Gilfoyle

+1

是6号线做与第五个对象不同的东西?如果只有5个对象,为什么还需要5个以上的线程?当你需要4倍的线程数时,肯定没有性能优势。 – Kayaman

+0

是的。尽管它们具有相同的源代码,但所有20个线程都将具有不同的操作。操作将根据提供给源代码的输入而有所不同。正如** Gilfoy **和** Svetlin Zarev **所建议的那样,我正在使用一个现在完美工作的实现。感谢您的意见。 –

回答

2

我觉得你有你的线程模型是错误的。目前你想要share这在并行环境中总是错误的。你应该做的是创建一个pipeline。要做到这一点,你有几个选择。

  1. 使用(阻塞/并发)队列在线程之间传递对象。在这种情况下,管道的每个阶段都有固定数量的工作线程,这些工作线程始终在运行并共享队列。一方面你有producer线程,当它们完成put()对象到队列,然后consumer线程take()之一,并开始处理它。 (1)使用threadpool充当队列。而不是在共享队列上执行put(),而是对共享或专用线程池执行submit()/execute()以将对象传递到管道的下一个阶段。这种方法的缺点是,现阶段必须知道提交任务的确切池,并知道如何创建要提交的runnable

PS:在我的答案我假设线程6执行不同于前面的5个线程的操作类型。如果这种假设不正确 - 解决方案(1)仍然是正确的,并且是前进的方向。

+0

谢谢。有用。你是对的。每个线程将执行不同类型的操作。 –

1

您可以定义要并行运行的线程数。例如,

ExecutorService executor = Executors.newFixedThreadPool(20); 

然后,您可以编写for循环来处理对象列表。

for(Object obj: objList) { 
    Runnable thread = new MyThreadImpl(obj); 
    executor.execute(thread); 
} 

这应该工作,按您的

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(); 
    } 
} 
1

对我来说,你在说的是Object pool pattern。对象池是包含指定数量对象的容器。从池中取出对象时,在放回池之前,该对象在池中不可用。

池应在诸如使用:使用同一对象的

  • 高频
  • 对象是非常大的,消耗多少内存
  • 对象需要太多的时间进行初始化
  • 对象使用大量IO操作(流,套接字,DB等)
  • 对象不是线程安全的

某些出版物不建议使用对象池,尤其是对于仅使用内存且不包含外部资源的对象。相关批评question

取决于你为什么需要这种模式。这里是implementation in Java