2016-09-27 13 views
4

私はint配列、要素numと4スレッドを持っているとします。 numを検索するために各スレッドに1/4の配列を与えています。 (検索方法は以下のとおりである)私の「トップレベル」でスレッド間の通信でのparellelの検索

public static boolean contains(int[] array, int minIdx, int maxIdx, int num) { ...} 

、私は配列の4四半期検索する4つのスレッドをスケジュールすることができますが、どのように私はすべてのスレッドは、すぐ一つとして検索を停止することを確認します(配列に重複がないと仮定すると、その要素はたかだか1回しか出現することはできません)。

P.S:私の4番目のスレッドが最初の反復で要素を見つけたとします。他の3人のユーザーが完了するのを待つのではなく、トップレベルのメソッドをすぐに返すようにします。

+0

。 – Kayaman

+0

* "それらの要素の1つが見つかるとすぐに" *ループ最適化を妨げる可能性のある単一のループ反復ごとに揮発性の読み込みが最小限であるため、最低限必要とする可能性があります。等価性検査が本当に高価でない限り、N回目の繰り返しをすべて確認することはコストがかかりません。警告出力は、オプティマイザが行う可能性のある推測よりも信頼性が高くなります。 – the8472

+0

@ the8472これは実装固有のものであるため、信頼性が高くありません。単一のJVM実行のアセンブリー出力を信頼するよりも、優れたプログラミング慣用句を維持することをお勧めします。 –

答えて

3

明示的なシグナリングが必要です。あなたは組み込みの中断メカニズムを考えているかもしれません。あるいは非常に簡単なので自分自身をロールバックするかもしれません。

1つのアイデア:すべてのスレッドの中でAtomicBooleanを共有し、それぞれのスレッドを定期的にチェックさせます。スレッドが答えを見つけると、スレッドはブール値を反転させます。

for (int i = start; i < end && !done.get();) { 
    for (int batchLimit = Math.min(i + BATCH_SIZE, end); i < batchLimit; i++) { 
     // your logic 
    } 
} 

これは、JITコンパイラが最適化するのが最も簡単な方法です。

値が変更されていない場合は、値をチェックする代償は非常に低くなります。 L3キャッシュに格納されます。その時点であなたが完了しているので、値が変更された場合は無関係です。

+0

しかし、フラグを使用することによって、それはブロックされますか?(スレッドセーフであることを保証するために、すべてのスレッドをブロックする必要があるため) –

+0

ブロッキングはまったくありません。これは普通の「揮発性の」読み取り操作ですが、非常に効率的です。 –

0

回答を見つけてスレッド間で共有するときにフラグを使用して通知します。 AtomicBooleanは良い選択です。 は、各スレッドから戻ってきているときにも)(サイズ4とカウントダウンのCountDownLatchを共有する例

for (int i = minIdxs ; i < maxIdxs && found.get() == false; ++i){...} 

のためにあなたのループの終了条件にブール値を追加します。

メインスレッドawait()を持っていると、メインスレッドで移動する前にすべてのスレッドが正常に終了していることを意味します。

+0

'Thread.join()'はスレッドの完了を待つのに十分です。そして、私は、各ターンでブール値をチェックするのではなく、バッチ処理を推奨しています(_definitely_)。 100人に1人の読者が犠牲になりましたが、1万人に1人の人がすべて、良い反応を得るためには本当に必要です。 –

+0

あなた自身がスレッドを作成しているのに 'join()'が使用されるかもしれませんが、 'ExecutorService'を使用していると言えばうまくいきません。しかし、どちらの場合でもラッチは機能します。しかし、私はバッチ処理の考え方が好きです。 –

+0

ExecutorServiceを使用すると、 'Future'が得られます。 –

0

コントローラのように動作するクラスを作成できます。このクラスは各スレッドを知り、すべてのスレッドはコントローラを知っています。 (オブザーバーパターンのような)

スレッドが答えを見つけたら、スレッドはコントローラにそれを伝えて、他のスレッドに停止を知らせることができます。すべてのスレッドが観察共有リソースと

class ControllerOfAllTheThreads{ 
ArrayList<TheClassesWhichDoTheSearch> list = new ArrayList<TheClassesWhichDoTheSearch>(); 

public void tellThemWeFoundHim(){ 
    for (TheClassesWhichDoTheSearch theThreads : list) { 
     if(theThreads.isAlive() && !theThreads.isInterrupted()) 
      theThreads.interrupt(); 
    } 
} 

}

関連する問題