簡體   English   中英

Java並發集合搜索

[英]Java Concurrent Collection Search

我已經用Java編程了一段時間,但對並發編程還是陌生的,所以請耐心等待!

我正在嘗試開發一個類,該類包含一組Collection類[例如ArrayLists],然后找到一個指定的值,它同時遍歷所有collection,如果找到給定的值,則停止所有線程。

我在下面粘貼了我的代碼,想知道是否有人知道在contains_multiple_collections()中如何捕獲返回的線程之一是否期貨返回了真值?

謝謝

格雷厄姆

public class CollectionGroup<V> extends ContainerGroup
{
//...
    public boolean contains(V value)
    {
        boolean containsValue = false;
        if (mCollections.size() == 1)
        {
            containsValue = mCollections.get(0).contains(value);
        }
        else
        {
            containsValue = contains_multiple_collections(value);
        }
        return containsValue;
    }

    private boolean contains_multiple_collections(V value)
    {
        // thread pool
        int numberProcessors = mCollections.size();
        ExecutorService es = Executors.newFixedThreadPool(numberProcessors);

        for (int i=0; i<numberProcessors; i++)
        {
            AbstractCollection<V> collection = mCollections.get(i);
            MyCallable callable = new MyCallable(collection,value);
            Future<Boolean> future = es.submit(callable);
            //...
        }

        return true;
    }

    private class MyCallable implements Callable<Boolean>
    {
        protected AbstractCollection<V> mCollection;
        protected V                     mValue;

        public MyCallable(AbstractCollection<V> collection, V value)
        {
            mCollection = collection;
            mValue      = value;
        }

        @Override
        public Boolean call() throws Exception
        {
            boolean ok = mCollection.contains(mValue);
            return ok;
        }
    } // class MyCallable

} // class CollectionGroup

包含不會僅僅因為您可能已經在另一個線程中找到該值而停止。 唯一的方法就是循環播放自己。

對於CPU密集型進程,最佳線程數可能是您擁有的內核數。 創建太多線程會增加開銷,從而降低解決方案的速度。

您還應該記得在完成后關閉()ExecutorService。

如果要加快搜索速度,我將維護一個“所有值的集合”,這可能比使用多個線程快10-100倍。

您可以使用ExecutorCompletionService。 只需保持take()ing(take()塊,直到存在完整的Future),直到獲得正確的結果,並在發現某些內容后將shutdownNow()作為基礎ExecturService。 一旦找到一個值,這不會立即停止所有線程。

您可以反復遍歷所有期貨,並使用零或幾乎為零的超時,使用get對其進行輪詢,但是更好的主意是為所有MyCallable提供回調,然后在找到匹配項時調用該回調。 然后,回調應該取消所有其他任務,可能是通過關閉ExecutorService

我建議使用一個靜態AtomicBoolean,當找到匹配項時將其設置。 然后,每個線程可以在繼續操作之前檢查該值。

問題是您的contains_multiple_collections方法沒有等待搜索完成。 您可以考慮兩種選擇。 第一種將涉及一些異步回調實現,其中contains方法不會阻塞,並且可能將回調/偵聽器對象作為參數。 第二個步驟是使contains方法塊直到確定結果為止。 我在下面概述了后一種方法的示例實現,尚未經過測試,因此請注意...

/*
 * contains_multiple_collections now blocks until the desired 
 * value is located or all searches have completed unsuccessfully...
 */
private boolean contains_multiple_collections(V value) {
    // thread pool
    int numberProcessors = mCollections.size();
    ExecutorService es = Executors.newFixedThreadPool(numberProcessors);

    Object lock = new Object();
    AtomicBoolean outcome = new AtomicBoolean(false);
    AtomicInteger remainingSearches = new AtomicInteger(mCollections.size());

    for (int i = 0; i < numberProcessors; i++) {
        AbstractCollection<V> collection = mCollections.get(i);
        es.submit(new MyRunnable(collection, value, lock, outcome, remainingSearches));
    }

    /* Wait for searches to run. This thread will be notified when all searches
     * complete without successfully locating the value or as soon as the
     * desired value is found.
     */
    synchronized (lock) {
        while (!outcome.get() && remainingSearches.get() > 0) {
            try {
                lock.wait();
            } catch (InterruptedException ex) {
                // do something sensible.
            }
        }
        es.shutdownNow();
    }

    return outcome.get();
}

private class MyRunnable implements Runnable {

    final AbstractCollection<V> mCollection;
    final V                     mValue;
    final Object                lock;
    final AtomicBoolean         outcome;
    final AtomicInteger         remainingSearches;

    public MyRunnable(AbstractCollection<V> mCollection, V mValue, 
            Object lock, AtomicBoolean outcome, AtomicInteger remainingSearches) {
        this.mCollection = mCollection;
        this.mValue = mValue;
        this.lock = lock;
        this.outcome = outcome;
        this.remainingSearches = remainingSearches;
    }

    public void run() {
        boolean ok = mCollection.contains(mValue);
        if (ok || remainingSearches.decrementAndGet() == 0) {
            synchronized (lock) {
                if (ok) {
                    outcome.set(true);
                }

                lock.notify();
            }
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM