2016-10-09 5 views
0

5つのスレッドを使ってテキストをコンマで数えます。テキストを5等分して分割し、それぞれのスレッドがそれ自身の部分で動作するようにします。テキストでコンマを数える(マルチスレッド)、私はそれを正しくやっていますか?

public class CommaCounter implements Runnable { 

    public static int commaCount = 0; // it's static so that all CommaCounter threads share the same variable 

    private String text; 
    private int startIndex; 
    private int endIndex; 

    public CommaCounter(String text, int startIndex, int endIndex) { 
     this.text = text; 
     this.startIndex = startIndex; 
     this.endIndex = endIndex; 
    } 

    @Override 
    public void run() { 

     for (int i = startIndex; i < endIndex; i++) { 
      if(text.charAt(i) == ','){ 
       commaCount++; // is incrementing OKAY? is there danger of thread interference or memory consistency errors? 
      } 
     } 
    } 
} 

、メイン方法:commaCountをインクリメントすることはすなわち、適切に行われている場合

public class Demo { 

    public static void main(String[] args) throws MalformedURLException, IOException, InterruptedException { 

     long startTime = System.currentTimeMillis(); 
     /* 
      I'll spare the code that was here for retrieving the text from a URL 
     */ 

     String text = stringBuilder.toString(); 

     Set<Thread> threadCollection = new HashSet<>(); 

     int threadCount = 5; 
     int textPerThread = text.length()/threadCount; 
     for (int i = 0; i < threadCount; i++) { 
      int start = i * textPerThread; 
      Thread t = new Thread(new CommaCounter(text, start, start + textPerThread)); 
      threadCollection.add(t); 
      t.start(); 
     } 

     for (Thread thread : threadCollection) { 
      thread.join(); // joining each CommaCounter thread, so that the code after the for loop doesn't execute prematurely 
     } 

     long endTime = System.currentTimeMillis(); 
     System.out.println("Counting the commas with " + threadCount + " threads took: " + (endTime - startTime) + "ms"); 
     System.out.println("Comma count: " + CommaCounter.commaCount); 
    } 

} 

は主に私が心配しているのスレッドのいずれかの危険性がある、私は右のそれをやっている場合、私はただ思ったんだけど干渉またはメモリーの一貫性エラー。また、なぜ私は実行時間が単なるスレッドでコンマを数える(それはほとんど同じでした)よりも良くないと思っていました。

助けていただけたら幸いです!

+1

これはうまくいかないので、java.util.concurrent.CallableをCommaCounterのクラスに実装することをお勧めします。これは、スレッドの終了後に結果を得ることができます。 – Eric

答えて

3

絶対に正しくありません。複数のスレッドから静的変数にアクセスしています。 AtomicIntegerまたは同期静的メソッドを使用します。

正確に、あなたのコメントで述べたように:)

それのAtomicInteger作るとgetAndIncrementまたはincrementAndGetメソッドを使用し、

または静的同期メソッドを作成し、

または同期ブロックを作成してどちらかこの場合は、同期するオブジェクトが同じであることを確認してください!このクラスCommaCounterにおける静的変数についてであるように、それはそれは、私はそれが並列分割を使用するので、この問題は正確

https://docs.oracle.com/javase/tutorial/essential/concurrency/forkjoin.html

枠組みフォークと一致し、参加推測CommaCounter.class

+0

Aha、得ました。ですから、基本的に3つの選択肢があります:1)静的変数commaCounterをAtomicIntegerにします。 2)同期ブロック内のrun()メソッドにcommaCounter ++ステートメントを置く。 3)インクリメントのために指定された同期メソッドを作成する –

+0

右か?また、すべてが同期されている限り、Runnableオブジェクト内の静的フィールド(commaCounterなど)に問題がありますか? –

+1

静的フィールドは単なるグローバル変数です。どの文脈で宣言されても全く問題ではありません。また、同じ変数にアクセスするすべてのスレッドが同じオブジェクト上で同期している限り、どのオブジェクトを同期させるかは関係ありません。 – yeoman

1

ことと技術を征服することができテキストを分割して新しいスレッドに割り当てます。また、「ステルス」テクニックを使用して、すべてのスレッドがビジー状態になっていることを確認します。

+0

これは、変数へのアクセスを同期する基本を理解した直後に、ステップ7程度の素晴らしい提案です。すぐに、揮発性のJavaフィールド、原子プリミティブ、java.util.Concurrentを理解することによって、フォーク/ジョインのような高レベルのフレームワーク内で何が起こっているのか把握する機会があります – yeoman

関連する問題