1

3 つのスレッドが 1 から 10 までの数字を順番に出力しようとするプログラムがありCountDownLatchます。カウントを維持するために a を使用しています。

しかし、プログラムは 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

4 に答える 4

4

しかし、プログラムは 1 を印刷した直後に停止します。

いいえ、これは起こりません。どのスレッドも終了しません。

countすべてのワーカーに独自のフィールドがあります。他のスレッドはこのフィールドに書き込みません。

したがって、if (count % 3 == id) {yieldtrueを持つスレッドは 1 つだけid = 0です。countまた、これはフィールドを変更する唯一のスレッドであり、それを変更すると、後続のループ反復で(count % 3 == id)生成され、3 つのスレッドすべてで無限ループが発生します。false

これを修正するには、 に変更countします。static

編集

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

于 2016-08-07T11:46:21.697 に答える
1

あなたの「カウント」はスレッドごとに異なる変数であるため、あるスレッドでそれを変更しても残りのスレッドには影響しません。

于 2016-08-07T11:45:46.573 に答える
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();
        }
    }
}

これで問題が解決することを願っています

于 2017-04-03T11:05:54.660 に答える