2016-08-07 44 views
1

私は、3つのスレッドが1から10の順に番号を印刷しようとしているプログラムを持っています。私はCountDownLatchを使ってカウントを保持しています。3つのスレッドを使って順番に番号を印刷する

しかし、プログラムはただ1

注印刷した後に停止します。私はAtomicInteger代わりのIntegerを使用して働くことができることを承知していますが。しかし、私は現在のコードで問題を見つけるために探しています。

public class Worker implements Runnable { 
    private int id; 
    private volatile Integer count; 
    private CountDownLatch latch; 

    public Worker(int id, Integer count, CountDownLatch latch) { 
     this.id = id; 
     this.count = count; 
     this.latch = latch; 
    } 

    @Override 
    public void run() { 
     while (count <= 10) { 
      synchronized (latch) { 
       if (count % 3 == id) { 
        System.out.println("Thread: " + id + ":" + count); 
        count++; 
        latch.countDown(); 
       } 
      } 
     } 
    } 

} 

主なプログラム:

public class ThreadSequence { 
    private static CountDownLatch latch = new CountDownLatch(10); 
    private volatile static Integer count = 0; 

    public static void main(String[] args) { 
     Thread t1 = new Thread(new Worker(0, count, latch)); 
     Thread t2 = new Thread(new Worker(1, count, latch)); 
     Thread t3 = new Thread(new Worker(2, count, latch)); 

     t1.start(); 
     t2.start(); 
     t3.start(); 

     try { 
      latch.await(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 

    } 
} 

編集プログラムAtomicIntegerと:

public class ThreadSequence { 
    private static AtomicInteger atomicInteger = new AtomicInteger(1); 

    public static void main(String[] args) throws InterruptedException { 
     Thread t1 = new Thread(new WorkerThread(0, atomicInteger)); 
     Thread t2 = new Thread(new WorkerThread(1, atomicInteger)); 
     Thread t3 = new Thread(new WorkerThread(2, atomicInteger)); 
     t1.start(); 
     t2.start(); 
     t3.start(); 

     t1.join(); 
     t2.join(); 
     t3.join(); 

     System.out.println("Done with main"); 
    } 
} 


public class WorkerThread implements Runnable { 
    private int id; 
    private AtomicInteger atomicInteger; 

    public WorkerThread(int id, AtomicInteger atomicInteger) { 
     this.id = id; 
     this.atomicInteger = atomicInteger; 
    } 

    @Override 
    public void run() { 
     while (atomicInteger.get() < 10) { 
      synchronized (atomicInteger) { 
       if (atomicInteger.get() % 3 == id) { 
        System.out.println("Thread:" + id + " = " + atomicInteger); 
        atomicInteger.incrementAndGet(); 
       } 
      } 

     } 
    } 
} 

答えて

4

しかし、プログラムがちょうどありません、これは何が起こるかではありません。1.

を印刷した後に停止します。いずれのスレッドも終了しません。

あなたはすべての労働者にcountというフィールドを持っています。他のスレッドはこのフィールドに書き込みません。

したがって、if (count % 3 == id) {の結果はtrueであり、これはid = 0のスレッドです。また、これはcountフィールドを変更し、それを修正する唯一のスレッドであり、(count % 3 == id)がその後のループ反復でfalseになり、3つのスレッドすべてに無限ループが発生します。

countからstaticに変更してください。

編集

IntegerAtomicIntegerとは対照的に変更可能です。これは、変更可能な値のintを保持するクラスです。 Integerフィールドを変更するたびに値が変更されますが、AtomicIntegerオブジェクトを使用すると、AtomicIntegerオブジェクト内の値のみが変更されますが、3つすべてのスレッドが同じAtomicIntegerインスタンスを使用し続けます。

+0

は 'AtomicInteger'、それはのAtomicInteger静的せずに動作すると、プログラムを更新し、あなたの問題を解決することを願っています。どうして? – Anurag

+1

@Anurag:答えを編集しました。違いは 'Integer'では' Integer'オブジェクト自体を置き換えますが、 'AtomicInteger'では' AtomicInteger'インスタンスのフィールドを変更します。どちらの場合でも 'final'修飾子を追加して何が起こるかを見てみてください。 – fabian

+0

JDKの' AtomicInteger'ソースから、 'int'値を保持しています。これはfinalではありません。しかし、Integerの場合は、最終的なint値を保持します。 したがって、 'Integer'が' int'を持っていて最終的ではなく、揮発性であった場合、理論的には動作します。 これは何を意味していますか? – Anurag

1

あなたの "カウント" はそうdoesnの1つのスレッドでそれを変え、各スレッドごとに異なる変数であります残りの部分には影響しないので、彼らはそれを行うことができる者がいなくても、それが変わるのを待っている。

1

Workerクラスには、countを静的メンバーとして保持します(クラス内のすべてのオブジェクトに共通)。

あなたが複数のスレッドを使用して連続番号を印刷するには、コードの下に使用することができます
0

-

import java.util.ArrayList; 
import java.util.List; 
import java.util.concurrent.ArrayBlockingQueue; 
import java.util.concurrent.BlockingQueue; 

public class ThreadCall extends Thread { 

    private BlockingQueue<Integer> bq = new ArrayBlockingQueue<Integer>(10); 
    private ThreadCall next; 

    public void setNext(ThreadCall t) { 
     this.next = t; 
    } 

    public void addElBQ(int a) { 
     this.bq.add(a); 
    } 

    public ThreadCall(String name) { 
     this.setName(name); 
    } 

    @Override 
    public void run() { 
     int x = 0; 
     while(true) { 
      try { 
       x = 0; 
       x = bq.take(); 
       if (x!=0) { 
        System.out.println(Thread.currentThread().getName() + " =>" + x); 
        if (x >= 100) System.exit(0); // Need to stop all running threads 
        next.addElBQ(x+1); 
       } 
      } catch (InterruptedException e) { 
       e.printStackTrace(); 
      } 
     } 
    } 

    public static void main(String[] args) { 
     int THREAD_COUNT = 10; 
     List<ThreadCall> listThread = new ArrayList<>(); 

     for (int i=1; i<=THREAD_COUNT; i++) { 
      listThread.add(new ThreadCall("Thread " + i)); 
     } 

     for (int i = 0; i < listThread.size(); i++) { 
      if (i == listThread.size()-1) { 
       listThread.get(i).setNext(listThread.get(0)); 
      } 
      else listThread.get(i).setNext(listThread.get(i+1)); 
     } 

     listThread.get(0).addElBQ(1); 

     for (int i = 0; i < listThread.size(); i++) { 
      listThread.get(i).start(); 
     } 
    } 
} 

私はこれが

関連する問題