2017-05-27 18 views
0

私はこの単純なスレッド減算プログラムを作成しました。 正常に動作しますが、出力の最後には3つのランダムな値が与えられます。私はそれを防ぐ方法は考えていません。 また、各スレッドが自分のカウンタを何回減らしたのかを数えなければなりません。誰かが私にこれを手伝ってもらえますか?単純なMultiThreadsプログラムの出力が間違っています

public class ThreadsExample implements Runnable { 
    static int counter = 100000; 

    static long time; 
    static long endtime; 
    static float finaltime; 
    static int value; 

    static void incrementCounter() { 
     System.out.println(Thread.currentThread().getName() + ": " + counter); 
     counter--;  
    } 

    @Override 
    public void run() {  
    time = System.nanoTime(); 
     while (counter >= 0) { 
      incrementCounter(); 
     } 
     endtime = System.nanoTime() - time; 
     finaltime = endtime; 

     System.out.println(finaltime/1000000000 + " sekundy"); 
    } 
    public static void main(String[] args) throws InterruptedException { 
     ThreadsExample threads = new ThreadsExample(); 
     Thread thread1 = new Thread(threads); 
     Thread thread2 = new Thread(threads); 
     Thread thread3 = new Thread(threads); 
     Thread thread4 = new Thread(threads); 

     thread1.start(); 
     thread2.start(); 
     thread3.start(); 
     thread4.start(); 

     if (counter <= 0) { 
      System.out.println("Thread 1,2,3,4^^^"); 
     } 
    } 
} 
+0

一方、同じスレッドインスタンスを各スレッドに渡しています。これにより、内部状態の異常が発生する可能性があります。それぞれのスレッドコンストラクタに対して新しいThreadsExampleを作成してみてください。また、 "Counter"は静的であり、すべてのインスタンスが本質的に正確な時刻に 'counter <0'を検出するので、各ThreadsExampleが本質的に同時に停止するように見えます。これは期待されていますか?または、各スレッドが独自の独立カウンタを管理するようにしたいですか? – pacifier21

+0

あなたは同期の形式がありません。したがって、各スレッドは、いくつかの値「> 0」を読み取り、「カウンタ」を減少させることができるので、「カウンタ」は、いくつかの値「<0」で終了する。さらに、各スレッドは 'finaltime'を値にします。そこに競合状態があります。 – Turing85

答えて

0

マルチスレッドプログラミングの落とし穴があります。 発生している可能性が2つあります。

  1. それをアクセスするスレッドが、それはあなたが条件(すなわち、カウンタ> = 0)に基づいてアトミック更新を行っていない、すぐ
  2. 現在の値です表示されない場合がありますので、あなたは、counterなどの揮発性を宣言していません。 スレッド1のためのあなたのチェックcounter >= 0はそれがカウンター> = 0

チェックアウトjava.util.concurrent.atomic.AtomicIntegerと信じているので、その後、2つのデクリメントカウンタ、その後、あまりにも1つのデクリメントし、それをスレッドスレッド、真である可能性があります。 counterとしてください。

0

私が正しくあなたの問題を理解していれば、このようにいくつかの調整を行ってみてください。

// Need to import Lock to protect synchronized logic 
import java.util.concurrent.locks.Lock; 
import java.util.concurrent.locks.ReentrantLock; 

public class ThreadsExample implements Runnable { 

    static int counter = 100000; 
    // Lock to help synchronize access to counter 
    static Lock lock = new ReentrantLock(); 

    // These should not be static - they should be local to each ThreadsExample 
    long time; 
    long endtime; 
    float finaltime; 
    // Didn't see where this was used, so I'm using to track mod count 
    int value; 

    // Doesn't need to be static 
    void incrementCounter() { 

     System.out.println(Thread.currentThread().getName() + ": " + counter); 
     counter--; 

    } 

    @Override 
    public void run() { 

     time = System.nanoTime(); 
     // Use this boolean to determine when to stop 
     boolean done = false; 
     while (!done) { 
      // Acquire the lock 
      lock.lock(); 
      try { 
       // Now that this thread owns the lock, it can check 
       // the counter without worrying about other threads 
       // making modifications 
       if (counter > 0) { 
        incrementCounter(); 
        // Increment the mod count (how many times this thread affected counter) 
        value++; 
       } else { 
        // We can stop here since counter is 0 or less 
        done = true; 
       } 
      } finally { 
       // Release the lock so other threads have a chance 
       lock.unlock(); 
      } 
     } 
     endtime = System.nanoTime() - time; 
     finaltime = endtime; 

     System.out.println(finaltime/1000000000 + " sekundy"); 
     // Print out the mod count 
     System.out.println(Thread.currentThread().getName() + " updated counter " + value + " times."); 

    } 

    public static void main(String[] args) throws InterruptedException { 
     // Create a new ThreadsExample for each Thread 
     // And give the threads readable names. 
     Thread thread1 = new Thread(new ThreadsExample(), "thread-1"); 
     Thread thread2 = new Thread(new ThreadsExample(), "thread-2"); 
     Thread thread3 = new Thread(new ThreadsExample(), "thread-3"); 
     Thread thread4 = new Thread(new ThreadsExample(), "thread-4"); 

     thread1.start(); 
     thread2.start(); 
     thread3.start(); 
     thread4.start(); 

     // Note: This will likely never get printed since it might take 
     // a few milliseconds for the other threads to "consume" the counter 
     if (counter <= 0) { 
      System.out.println("Thread 1,2,3,4^^^"); 
     } 
    } 
} 

私もThreadsExampleにローカル名の変数を与える代わりににThread.currentThread()を使用することをお勧めしますのgetName()。それはあなた次第です。

+0

ええ、それは私が望んだものですが、コンソールの終わりを見てください。 0に達すると、3つの乱数の出力が得られます。 – Nexog

+0

3つの乱数が表示されません。これは私のコンソール出力の終わりです:8.759564 sekundy thread-4 updated counter 22134 times。 8.941281 sekundy スレッド1更新カウンタ25116回。 8.759831 sekundy スレッド3更新カウンタ32714回。 8.761887 sekundy スレッド2更新カウンタ20043回。 – pacifier21

+0

私はあなたが今話していることを知っていると思います。他のスレッドはまだ完了しておらず、時刻のプリント直前にゼロ以外のカウンタ値を報告しています。私は別のアプローチを試みるつもりですが、私は答えを更新します。 – pacifier21

0
public class ThreadsExample implements Runnable { 

    private static volatile int counter = 100000; // 10k 
    private int counterDecrements = 0; // zero decrements 

    // Doesn't need to be static, but should likely be synchronized 
    private void incrementCounter() { 

     System.out.println(Thread.currentThread().getName() + ": " + counter); 
     // counter--; 
     // ++counterDecrements; 

    } 

    @Override 
    public void run() { 

     long startTime, endTime, timeDiff; 

     startTime = System.currentTimeMillis(); 
     while (counter >= 0) { 
      incrementCounter(); // thread loop 
      --counter; 
      ++counterDecrements; 

     } 
     endTime = System.currentTimeMillis(); 
     timeDiff = startTime - endTime; // time diffrence is how long it took. 

     System.out.println((timeDiff/1000000000) + " sekundy"); 
     // Print out the mod count 
     System.out.println(Thread.currentThread().getName() + " Decremented counter " + counterDecrements + " times."); 

    } 

    public static void main(String[] args) throws InterruptedException { 
     // Create a new ThreadsExample for each Thread 
     // And give the threads readable names. 
     Thread thread1 = new Thread(new ThreadsExample(), "thread-1"); 
     Thread thread2 = new Thread(new ThreadsExample(), "thread-2"); 
     Thread thread3 = new Thread(new ThreadsExample(), "thread-3"); 
     Thread thread4 = new Thread(new ThreadsExample(), "thread-4"); 

     thread1.start(); 
     thread2.start(); 
     thread3.start(); 
     thread4.start(); 


     if (counter == 0) { 
      System.out.println("Thread 1,2,3,4^^^^"); 
     } 
    } 
} 
関連する問題