使用 3 个线程按顺序打印数字
Printing numbers in sequence using 3 threads
我有一个程序,其中 3 个线程试图按从 1 到 10 的顺序打印数字。我正在使用 CountDownLatch
来保持计数。
但是程序刚打印完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();
}
}
}
}
}
你的"count"是每个线程的不同变量,所以在一个线程中改变它不会影响其余的,所以他们都在等待它改变,没有人能做到.
But the program stops just after printing 1.
不,这不是发生的事情。 None 个线程终止。
您在每个工人中都有自己的 count
字段。其他线程不写入此字段。
因此只有一个线程,其中 if (count % 3 == id) {
产生 true
,也就是带有 id = 0
的线程。此外,这是唯一一个曾经修改 count
字段的线程,修改它会导致 (count % 3 == id)
在后续循环迭代中产生 false
,从而导致所有 3 个线程陷入无限循环。
将 count
更改为 static
以解决此问题。
编辑
与Integer
相反,AtomicInteger
是可变的。它是一个 class,其中包含一个可以修改的 int
值。使用 Integer
字段的每次修改都会替换它的值,但是使用 AtomicInteger
你只能修改 AtomicInteger
对象内的值,但是所有 3 个线程继续使用相同的 AtomicInteger
实例.
将 count
保留为 Worker class 中的静态成员 - 对于 class 中的所有对象都是通用的。
您可以使用以下代码使用多线程打印序列号 -
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();
}
}
}
希望这能解决您的问题
我有一个程序,其中 3 个线程试图按从 1 到 10 的顺序打印数字。我正在使用 CountDownLatch
来保持计数。
但是程序刚打印完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();
}
}
}
}
}
你的"count"是每个线程的不同变量,所以在一个线程中改变它不会影响其余的,所以他们都在等待它改变,没有人能做到.
But the program stops just after printing 1.
不,这不是发生的事情。 None 个线程终止。
您在每个工人中都有自己的 count
字段。其他线程不写入此字段。
因此只有一个线程,其中 if (count % 3 == id) {
产生 true
,也就是带有 id = 0
的线程。此外,这是唯一一个曾经修改 count
字段的线程,修改它会导致 (count % 3 == id)
在后续循环迭代中产生 false
,从而导致所有 3 个线程陷入无限循环。
将 count
更改为 static
以解决此问题。
编辑
与Integer
相反,AtomicInteger
是可变的。它是一个 class,其中包含一个可以修改的 int
值。使用 Integer
字段的每次修改都会替换它的值,但是使用 AtomicInteger
你只能修改 AtomicInteger
对象内的值,但是所有 3 个线程继续使用相同的 AtomicInteger
实例.
将 count
保留为 Worker class 中的静态成员 - 对于 class 中的所有对象都是通用的。
您可以使用以下代码使用多线程打印序列号 -
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();
}
}
}
希望这能解决您的问题