java - 有效阻塞查询的建议

标签 java collections blocking concurrency

我想将元组对象存储在并发 java 集合中,然后有一个高效的阻塞查询方法,该方法返回第一个与模式匹配的元素。如果没有这样的元素可用,它将阻塞直到出现这样的元素。

例如,如果我有一个类:

public class Pair {
  public final String first;
  public final String Second;
  public Pair( String first, String second ) {
    this.first = first;
    this.second = second;
  }
}

还有一个像这样的集合:

public class FunkyCollection {
  public void add( Pair p ) { /* ... */ }
  public Pair get( Pair p ) { /* ... */ }
}

我想这样查询:

myFunkyCollection.get( new Pair( null, "foo" ) );

它返回第一个可用的对,其中 second 字段等于“foo”或 block ,直到添加这样的元素。另一个查询示例:

myFunkyCollection.get( new Pair( null, null ) );

应该返回第一个可用的对,无论它的值是什么。

是否已经存在解决方案?如果不是这种情况,您建议如何实现 get( Pair p ) 方法?

说明: get( Pair p) 方法还必须移除元素。名字的选择不是很聪明。更好的名称是 take( ... )

最佳答案

这是一些源代码。它与 cb160 所说的基本相同,但是拥有源代码可能有助于清除您可能仍然存在的任何问题。特别是 FunkyCollection 上的方法必须同步。

正如 meriton 指出的那样,每次添加新对象时,get 方法都会对每个阻塞的 get 执行 O(n) 扫描。它还执行 O(n) 操作来删除对象。这可以通过使用类似于链接列表的数据结构来改进,您可以在其中将迭代器保留到最后检查的项目。我没有提供此优化的源代码,但如果您需要额外的性能,实现起来应该不会太困难。

import java.util.*;

public class BlockingQueries
{
    public class Pair
    {
        public final String first;
        public final String second;
        public Pair(String first, String second)
        {
            this.first = first;
            this.second = second;
        }
    }

    public class FunkyCollection
    {
        final ArrayList<Pair> pairs = new ArrayList<Pair>();

        public synchronized void add( Pair p )
        {
            pairs.add(p);
            notifyAll();
        }

        public synchronized Pair get( Pair p ) throws InterruptedException
        {
            while (true)
            {
                for (Iterator<Pair> i = pairs.iterator(); i.hasNext(); )
                {
                    Pair pair = i.next();
                    boolean firstOk = p.first == null || p.first.equals(pair.first);
                    boolean secondOk = p.second == null || p.second.equals(pair.second);
                    if (firstOk && secondOk)
                    {
                        i.remove();
                        return pair;                
                    }
                }
                wait();
            }
        }   
    }

    class Producer implements Runnable
    {
        private FunkyCollection funkyCollection;

        public Producer(FunkyCollection funkyCollection)
        {
            this.funkyCollection = funkyCollection;
        }

        public void run()
        {
            try
            {
                for (int i = 0; i < 10; ++i)
                {
                    System.out.println("Adding item " + i);
                    funkyCollection.add(new Pair("foo" + i, "bar" + i));
                    Thread.sleep(1000);
                }
            }
            catch (InterruptedException e)
            {
                Thread.currentThread().interrupt();
            }
        }
    }

    public void go() throws InterruptedException
    {
        FunkyCollection funkyCollection = new FunkyCollection();
        new Thread(new Producer(funkyCollection)).start();
        System.out.println("Fetching bar5.");
        funkyCollection.get(new Pair(null, "bar5"));
        System.out.println("Fetching foo2.");
        funkyCollection.get(new Pair("foo2", null));
        System.out.println("Fetching foo8, bar8");
        funkyCollection.get(new Pair("foo8", "bar8"));
        System.out.println("Finished.");
    }

    public static void main(String[] args) throws InterruptedException
    {
        new BlockingQueries().go();
    }
}

输出:

Fetching bar5.
Adding item 0
Adding item 1
Adding item 2
Adding item 3
Adding item 4
Adding item 5
Fetching foo2.
Fetching foo8, bar8
Adding item 6
Adding item 7
Adding item 8
Finished.
Adding item 9

请注意,我将所有内容都放在一个源文件中以使其更易于运行。

关于java - 有效阻塞查询的建议,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2035282/

相关文章:

linux - Linux阻塞与非阻塞串行读取

java - 数学公式

collections - 以降序遍历 collections.Counter() 实例的 Pythonic 方式?

jquery - ASP.NET MVC 方括号集合模型绑定(bind)

excel - VBA 集合 - 将值从静态范围读入集合

css - 移动显示 :Block link text to the bottom of a div

java - SQLite查询: get all columns of a row(android)?

java - 访问 EJB 分离的接口(interface)时出现 IllegalAccessException

java - 我如何在静态方法中刷新相同的 Activity

cocoa-touch - -[NSInputStream 是否读取 :maxLength:] block?