我使用AMQP来排队多个线程进行图搜索。该图不会被单独的线程以固定的时间间隔修改。最好的并发模型是什么,可以等待所有活动搜索完成,阻塞这些线程,并允许更新线程在解除阻塞搜索线程之前修改图形?
我一直在通过http://docs.oracle.com/javase/tutorial/essential/concurrency/阅读,但似乎找不到任何与我的模型完全匹配的东西。
有什么建议吗?
谢谢!
编辑:我使用ExecutorService来处理线程。
发布于 2014-05-31 04:00:46
你真的需要阻止吗?也许非阻塞的写入时复制就足够了。
更新线程应该克隆当前的图结构,并在克隆上应用更新。一旦更新完成,新的图就应该被公布--只需覆盖共享引用。
搜索线程应该将图形引用保存到局部变量或作用域一次并使用它。共享图永远不会被修改,因此不需要任何锁定和等待。
优点:
缺点:
也可以仅将写入时复制应用于图形的一部分。尤其是当图是消耗内存的结构时。然而,这是一个相当难的话题--参见MVCC和STM (Software Transactional Memory)。
发布于 2014-05-31 02:50:37
我不熟悉AMQP,但这是一个生产者/消费者的问题,所以在Java中有几种方法可以解决这个问题。这是一个关于Futures和ReentrantLock的非常快速和肮脏的例子:
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Demo {
private static Random rand = new Random();
private static final Lock lock = new ReentrantLock();
private static boolean updating = false;
private static List<Future<Integer>> futureList = new ArrayList<Future<Integer>>();
private static ExecutorService pool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
private static Callable<Integer> callable = new Callable<Integer>() {
@Override
public Integer call() {
return rand.nextInt();
}
};
private static void doUpdate() {
if (lock.tryLock()) {
updating = true;
try {
for (Future<Integer> future : futureList) {
System.out.println(future.get());
}
futureList.clear();
} catch (Exception e) {
e.printStackTrace();
} finally {
System.out.println();
lock.unlock();
updating = false;
}
}
}
public static void main(String[] args) throws Exception {
// submitter thread
new Thread(new Runnable() {
@Override
public void run() {
int submitCount = 0;
while (submitCount < 10) {
if (!updating) {
futureList.add(pool.submit(callable));
submitCount++;
}
try {
Thread.sleep(1000); // arbitrary
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
// update thread
new Thread(new Runnable() {
@Override
public void run() {
int updateCount = 0;
while (updateCount < 5) {
doUpdate();
updateCount++;
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
}
}我将更新线程设置为提交线程频率的一半。所以,如果你运行它,你会看到更新程序每次运行时都会去掉两个整数。提交线程必须等待,直到更新程序释放锁。
还有其他方法-查看BlockingQueue接口:您可能想要进行试验。
https://stackoverflow.com/questions/23959948
复制相似问题