[英]Printing numbers in sequence using 3 threads
I have a program where 3 Threads are trying to print numbers in sequence from 1 to 10. I am using a CountDownLatch
to keep keep a count.我有一个程序,其中 3 个线程试图按从 1 到 10 的顺序打印数字。我正在使用
CountDownLatch
来保持计数。
But the program stops just after printing 1.但是程序在打印 1 后就停止了。
Note: I am aware that using AtomicInteger
instead of Integer
can work.注意:我知道使用
AtomicInteger
而不是Integer
可以工作。 But I am looking to find out the issue in the current code.但我希望找出当前代码中的问题。
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();
}
}
}
}
}
Main program:主程序:
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();
}
}
}
Edited program with AtomicInteger
:使用
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();
}
}
}
}
}
But the program stops just after printing 1.
但是程序在打印 1 后就停止了。
No this is not what happens.不,这不是发生的事情。 None of the threads terminate.
没有一个线程终止。
You have a own count
field in every worker.每个工人都有自己的
count
字段。 Other threads do not write to this field.其他线程不写入此字段。
Therefore there is only one thread, where if (count % 3 == id) {
yields true
, which is the one with id = 0
.因此只有一个线程,其中
if (count % 3 == id) {
产生true
,即id = 0
线程。 Also this is the only thread that ever modifies the count
field and modifying it causes (count % 3 == id)
to yield false
in subsequent loop iterations, causing an infinite loop in all 3 threads.这也是唯一一个修改过
count
字段并修改它导致(count % 3 == id)
在后续循环迭代中产生false
线程,从而导致所有 3 个线程中的无限循环。
Change count
to static
to fix this.将
count
更改为static
以解决此问题。
Edit编辑
In contrast to Integer
AtomicInteger
is mutable.与
Integer
相比, AtomicInteger
是可变的。 It is a class that holds a int
value that can be modified.它是一个包含可以修改的
int
值的类。 Using Integer
every modification of the field replaces it's value, but using AtomicInteger
you only modify the value inside the AtomicInteger
object, but all 3 threads continue using the same AtomicInteger
instance.使用
Integer
字段的每次修改都会替换它的值,但使用AtomicInteger
您只能修改AtomicInteger
对象内的值,但所有 3 个线程继续使用相同的AtomicInteger
实例。
您的“计数”是每个线程的不同变量,因此在一个线程中更改它不会影响其余线程,因此他们都在等待它更改,而没有任何人可以做到。
将count
保持为 Worker 类中的静态成员 - 对于类中的所有对象都是通用的。
You can use below code to print sequential numbers using multiple threads -您可以使用以下代码使用多个线程打印序列号 -
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();
}
}
}
I hope this will resolve your problem我希望这能解决你的问题
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.