0

wordCount(CharacterReader charReader)文字のストリームを受け取り、それらを単語に変換する関数があります。

Collection<CharacterReader> characerReaders複数の文字ストリームを含むもあります。コレクション内のリーダーの数はさまざまです。すべてのストリームから読み取り、すべての単語の数を取得したいと考えています。

スレッドについて少し混乱しており、これに似た例が見つかりませんでした。基本的に、複数のスレッドが単語を SortedMap に出力して、リアルタイムの合計単語数を取得できるようにする必要があります。

どうすればこれを行うことができますか?

ありがとう

4

3 に答える 3

2
  1. 複数のスレッドがマップに書き込む場合は、 aと a のConcurrentSkipListMap両方であるa を使用する必要があります。SortedMapConcurrentMap
  2. 関数を呼び出す(前述のマップにアクセスする)CharacterReaderコレクション内のfor each を作成できます。RunnablewordCount
  3. を作成Runnableできる s を作成した後ExecutorService(たとえば を使用Executors.newCacheThreadPool())、すべてのRunnables を渡し、それらが終了するのを待ちます ( classのjavadocExecutorServiceの例を参照してください)。

Runnableに送信する直前に を作成することもできますExecutorService

于 2012-07-18T20:48:18.563 に答える
1

ソートされたマップをカプセル化するクラスを作成WordMapし、マップへのすべてのアクセスが適切に同期されるようにします。または、すでにスレッドセーフになっている並行マップを使用してください。

このクラスのインスタンスを作成します。Executorsクラスを使用しExecutorServiceて、必要な特性を持つ を作成します。

次に、コレクションを反復処理し、リーダーごとにCallableまたはを作成しRunnable、このリーダーで見つかった単語で WordMap インスタンスを埋め、これをCallableまたはRunnableに送信しExecutorServiceます。

于 2012-07-18T20:46:30.333 に答える
1

vainolo と JB の回答はどちらも適切です。

1 つ追加します。それは、ワード カウントを格納する高度な並行データ構造を作成する方法の説明です。

vainolo が言ったように、ConcurrentSkipListMapは必要な基本的なデータ構造です。これは、並べ替えと同時実行の両方であるためです。それを有効に利用するには、ロックを行わないようにする必要があります。つまり、ロック、読み取り、書き込み、ロック解除のサイクルを含むパターンを避ける必要があります。これには 2 つの結果があります。1 つ目は、マップに新しい単語を配置する際にロックを使用しないことと、既存の単語のカウントをインクリメントする場合にロックを使用しないことです。

ConcurrentMap のputIfAbsentメソッドを使用して、マップに新しいものを安全に追加できます。ただし、それだけでは十分ではありません。使用するたびに潜在的な値を提供する必要があり、コストがかかる可能性があるからです。最も簡単な方法は、一種のダブルチェック ロック パターンを使用することです。最初に単純に既存の値を取得しようとし、存在しない場合は、putIfAbsent を使用して新しい値を追加します (単純にput を呼び出します。同時に put する 2 つのスレッド間で競合が発生する可能性があるためです)。

マップに整数を格納するのではなく、それ自体が整数を含むオブジェクトを格納することで、ロックを使用しないインクリメントを簡単に行うことができます。そうすれば、インクリメントされた値をマップに入れる必要はなく、すでにそこにあるオブジェクトをインクリメントするだけです。AtomicIntegerはこれに適した候補のようです。

それをまとめると、次のようになります。

public class WordCounts {
    private final ConcurrentMap<String, AtomicInteger> counts
         = new ConcurrentSkipListMap<String, AtomicInteger>();

    public void count(String word) {
        AtomicInteger count = getCount(word);
        count.incrementAndGet();
    }

    private AtomicInteger getCount(String word) {
        AtomicInteger count = counts.get(word);
        if (count == null) {
            AtomicInteger newCount = new AtomicInteger();
            count = counts.putIfAbsent(word, newCount);
            if (count == null) count = newCount;
        }
        return count;
    }
}
于 2012-07-18T21:30:20.280 に答える