我有一个程序,其中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();
}
}
}
}
}
答案 0 :(得分:4)
但程序在打印1后就会停止。
不,这不是会发生什么。没有线程终止。
每个工作人员都有一个自己的if (count % 3 == id) {
字段。其他线程不写入此字段。
因此,只有一个主题,其中true
会产生id = 0
,count
就是(count % 3 == id)
。此外,这是唯一修改false
字段并修改它的线程导致count
在后续循环迭代中产生static
,导致所有3个线程中出现无限循环。
将Integer
更改为AtomicInteger
以解决此问题。
修改强>
与int
相比Integer
是可变的。它是一个包含可以修改的AtomicInteger
值的类。使用AtomicInteger
字段的每次修改都会替换它的值,但使用AtomicInteger
只能修改{{1}}对象内的值,但所有3个线程继续使用相同的{{1}}实例
答案 1 :(得分:1)
您的“count”是每个线程的不同变量,因此在一个线程中更改它不会影响其余线程,因此它们都在等待它进行更改,而没有任何一个可以执行此操作。
答案 2 :(得分:1)
将count
作为静态成员保留在Worker类中 - 对于类中的所有对象都是通用的。
答案 3 :(得分: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();
}
}
}
我希望这会解决您的问题