J'ai un programme dans lequel 3 threads tentent d'imprimer des nombres de 1 à 10 en séquence. J'utilise un CountDownLatch
pour garder un compte.Impression de numéros en séquence à l'aide de 3 threads
Mais le programme arrête juste après l'impression 1.
Note: Je suis conscient du fait que l'utilisation AtomicInteger
au lieu de Integer
peut fonctionner. Mais je cherche à trouver le problème dans le code actuel.
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();
}
}
}
}
}
Programme principal:
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();
}
}
}
programme édité avec 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();
}
}
}
}
}
mis à jour le programme avec 'AtomicInteger' et il fonctionne sans AtomicInteger statique . Pourquoi? – Anurag
@Anurag: Édité la réponse.La différence est la suivante: avec 'Integer' vous remplacez l'objet' Integer' lui-même, mais avec 'AtomicInteger' vous modifiez un champ de l'instance' AtomicInteger'. Essayez d'ajouter le modificateur 'final' dans les deux cas et voyez ce qui se passe ... – fabian
De la source JDK de' AtomicInteger' je vois qu'il contient une valeur 'int' qui n'est pas finale. Mais dans le cas de 'Integer', il contient une valeur' int' qui est finale. Donc, dans le cas où 'Integer' avait un' int' qui était non-final et volatile, théoriquement cela fonctionnerait. C'est ce que vous vouliez dire? – Anurag