首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >寻找java并发模型建议

寻找java并发模型建议
EN

Stack Overflow用户
提问于 2014-05-31 01:09:46
回答 2查看 114关注 0票数 2

我使用AMQP来排队多个线程进行图搜索。该图不会被单独的线程以固定的时间间隔修改。最好的并发模型是什么,可以等待所有活动搜索完成,阻塞这些线程,并允许更新线程在解除阻塞搜索线程之前修改图形?

我一直在通过http://docs.oracle.com/javase/tutorial/essential/concurrency/阅读,但似乎找不到任何与我的模型完全匹配的东西。

有什么建议吗?

谢谢!

编辑:我使用ExecutorService来处理线程。

EN

回答 2

Stack Overflow用户

发布于 2014-05-31 04:00:46

你真的需要阻止吗?也许非阻塞的写入时复制就足够了。

更新线程应该克隆当前的图结构,并在克隆上应用更新。一旦更新完成,新的图就应该被公布--只需覆盖共享引用。

搜索线程应该将图形引用保存到局部变量或作用域一次并使用它。共享图永远不会被修改,因此不需要任何锁定和等待。

优点:

  • 无需锁定和等待读取器,
  • 如果更新失败,读取器仍使用旧图形进行长时间运行和偶尔更新,其中读取次数多于structure
  • ideal收集器处理旧图形的次数

缺点:

  • 一些读者可能会在更新之前开始操作旧数据-这可以通过检查对图的原始引用是否更改并最终重新启动整个operation.
  • multiple编写器来解决,这可能会在图中引入冲突,但它可以通过几种冲突解决技术来解决,最简单的是忽略以前的更改并覆盖("Take some“)。

也可以仅将写入时复制应用于图形的一部分。尤其是当图是消耗内存的结构时。然而,这是一个相当难的话题--参见MVCCSTM (Software Transactional Memory)

票数 1
EN

Stack Overflow用户

发布于 2014-05-31 02:50:37

我不熟悉AMQP,但这是一个生产者/消费者的问题,所以在Java中有几种方法可以解决这个问题。这是一个关于Futures和ReentrantLock的非常快速和肮脏的例子:

代码语言:javascript
复制
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接口:您可能想要进行试验。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23959948

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档