Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2012/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
将读取同步到java集合_Java_Thread Safety - Fatal编程技术网

将读取同步到java集合

将读取同步到java集合,java,thread-safety,Java,Thread Safety,所以我想要一个存储一系列股票报价的arraylist。但我会跟踪每一个的出价、要价和最后一个价格 当然,在任何时候,给定股票的买卖或最后一次交易都可能发生变化 我有一个更新价格的线程和一个读取它们的线程 我想确保阅读时没有其他线程更新价格。所以我看了同步收集。但这似乎只会在另一个线程向arraylist添加或删除条目时阻止读取 现在,我开始讨论包装器方法: public class Qte_List { private final ArrayList<Qte> the_list;

所以我想要一个存储一系列股票报价的arraylist。但我会跟踪每一个的出价、要价和最后一个价格

当然,在任何时候,给定股票的买卖或最后一次交易都可能发生变化

我有一个更新价格的线程和一个读取它们的线程

我想确保阅读时没有其他线程更新价格。所以我看了同步收集。但这似乎只会在另一个线程向arraylist添加或删除条目时阻止读取

现在,我开始讨论包装器方法:

public class Qte_List {
private final ArrayList<Qte> the_list;

public void UpdateBid(String p_sym, double p_bid){
    synchronized (the_list){
        Qte q = Qte.FindBySym(the_list, p_sym);
        q.bid=p_bid;}
}

public double ReadBid(String p_sym){
    synchronized (the_list){
        Qte q = Qte.FindBySym(the_list, p_sym);
        return q.bid;}
}
公共类Qte\u列表{
私有最终阵列列出_列表;
公共无效更新ID(字符串p_sym,双p_bid){
已同步(_列表){
Qte q=Qte.FindBySym(列表,p_-sym);
q、 bid=p_bid;}
}
公共双读标(字符串p_sym){
已同步(_列表){
Qte q=Qte.FindBySym(列表,p_-sym);
返回q.bid;}
}
因此,我想用这个来完成的只是一个线程可以同时做任何事情——阅读或更新列表的内容。我的方法对吗


谢谢。

是的,这将起作用,无论如何,您不需要自己做,因为它已经在Collections框架中实现了


这看起来是一个合理的方法。不过,吹毛求疵,您可能不应该在同步块中包含return语句:

public double ReadBid(String p_sym){
    double bid;
    synchronized (the_list) {
        Qte q = Qte.FindBySym(the_list, p_sym);
        bid = q.bid;
    }

    return bid;
}

我不确定这只是我的口味,还是有一些并发性问题,但至少在我看来,它看起来更干净;-)。

是的,你走的是正确的,这应该行得通


但是为什么不使用已经同步的现有集合并提供键值查找呢?

您的方法应该可以做到这一点,但是正如您所说的,一次只能有一个读写器。这不是非常可扩展的

这里有一些方法可以在不降低线程安全性的情况下提高性能。
例如,您可以使用。这将允许一次有多个读卡器,但当有人获得写锁时,所有其他人都必须等待他完成

另一种方法是使用适当的集合。似乎可以使用的线程安全实现来交换列表。请查看可能的候选列表

编辑:

假设您需要为您的地图排序,请查看接口。

您所做的工作,但每次想读取或更新元素的值时锁定整个列表是不可伸缩的。如果这不重要,那么您对您所拥有的就很好。如果您想使其更具伸缩性,请考虑以下……/P> 您没有说明是否需要对_列表进行结构更改(添加或删除元素),但如果不需要,一个很大的改进是将对FindBySym()的调用移到同步块之外。然后,您可以在q(Qte对象)上同步,而不是在_列表上同步。这样可以同时更新不同的Qte对象。此外,如果可以使Qte对象不可变,实际上根本不需要任何同步。(要更新,只需使用_list[i]=new Qte(…))

如果您确实需要能够对列表进行结构更改,则可以使用ReentrantReadWriteLock来允许并发读取和独占写入


我也很好奇为什么你想使用ArrayList而不是同步HashMap。

据我所知,你是在使用map来存储报价;报价的数量永远不会改变,但每个报价都可以读取或修改以反映当前的价格。重要的是要知道,锁定集合只能防止更改映射中引用对象的位置:它不会以任何方式限制对这些引用内容的修改。如果要限制访问,必须对引用对象提供锁定

查看您的代码,但我不认为您存在严重的同步问题。如果您尝试在写入的同时执行读取,您将在写入之前或之后获得价格。如果您不知道写入将要发生,这对您来说应该无关紧要。您可能需要在更高级别上锁定,以便

if (getBidPrice(mystock)<10.0) {
  sell(10000);
}

<代码>如果(GETBIDESPLY(MyStand)同步列表不能工作,因为他更新在同步化的块哈希表中的条目的属性(和vector)是预JDK 1.2并且应该避免。相反,考虑集合。创建线程安全HashMap。此外,尽管OP没有明确说明,但我怀疑引号需要按照典型的订购单进行订购。您是否试图防止在读取的同时写入Quote对象?如果是这样,锁定集合将无法实现这一点。请参阅我的答案。HashMap是否能起到很大作用更有意义。我可能默认会不假思索地列出太多内容。单个Qte对象上的不可变内容可能有助于解决部分问题。但我需要多做一些工作来理解它。是什么语法使Qte对象不可变,或者我将进行搜索。此外,不可变是否意味着要“更改”对象,我需要重新分配它?(我看到响应中的文本说,“要更新,只需使用_list[i]=new Qte(…)”Immutable意味着“不能更改”。例如字符串是不可变的,而StringBuffers是可变的。您不能更改字符串对象的值(例如,您不能说String s=“a”;s.append(“b”);不可变的Qte类将bid price、ask price和last price作为最终成员变量,并将这3个值传递给构造函数。成员变量可以是公共的,也可以每个变量都有一个getter(但没有setter)。另外,关于DJClayworth的评论“您可以在写入之前获得价格,也可以在写入之后获得价格”,只有当Qte.bid是32位(或更少)值或volatile.F时才是如此