Ich habe den folgenden Code entwickelt, um ein realistisches Szenario nachzuahmen.
100 Aufgaben werden parallel ausgeführt und sie aktualisieren ihren abgeschlossenen Status an das Hauptprogramm. Ich verwende eine CountDownLatch, um auf den Abschluss der Aufgabe zu warten.
import java.util.concurrent.*;
import java.util.*;
public class Runner {
// Should be replaced with Collections.synchronizedList(new ArrayList<Integer>())
public List<Integer> completed = new ArrayList<Integer>();
/**
* @param args
*/
public static void main(String[] args) {
Runner r = new Runner();
ExecutorService exe = Executors.newFixedThreadPool(30);
int tasks = 100;
CountDownLatch latch = new CountDownLatch(tasks);
for (int i = 0; i < tasks; i++) {
exe.submit(r.new Task(i, latch));
}
try {
latch.await();
System.out.println("Summary:");
System.out.println("Number of tasks completed: "
+ r.completed.size());
} catch (InterruptedException e) {
e.printStackTrace();
}
exe.shutdown();
}
class Task implements Runnable {
private int id;
private CountDownLatch latch;
public Task(int id, CountDownLatch latch) {
this.id = id;
this.latch = latch;
}
public void run() {
Random r = new Random();
try {
Thread.sleep(r.nextInt(5000)); //Actual work of the task
} catch (InterruptedException e) {
e.printStackTrace();
}
completed.add(id);
latch.countDown();
}
}
}
Wenn ich die Anwendung 10 mal und mindestens 3 bis 4 mal lief das Programm nicht korrekte Anzahl der abgeschlossenen Aufgaben. Idealerweise sollte 100 gedruckt werden (wenn keine Ausnahmen vorkommen). Aber in einigen Fällen war es Drucken 98, 99 usw.
So beweist es, dass gleichzeitige Updates von ArrayList wird keine korrekten Ergebnisse geben.
Wenn ich die ArrayList durch eine synchronisierte Version ersetze, gibt das Programm die korrekten Ergebnisse aus.
"Es ist meine Erfahrung, dass beide Objekte gut hinzugefügt wurden" möchte nur darauf hinweisen, dass dies nur reines Glück ist. Wahrscheinlich ist das Fenster für ein Datenbeschädigungsproblem mit ArrayList extrem klein, aber es existiert immer noch –
Richtig, und das ist mein Punkt. In den allermeisten Fällen wird es kein Problem geben. aber wir programmieren nicht auf die meisten Fälle. Deshalb empfehle ich dringend die Verwendung von ArrayList. – derivation