Я придумал следующий код для имитации сценария реального мира.
100 задач выполняются параллельно, и они обновляют свое завершенное состояние для основной программы. Я использую CountDownLatch для ожидания завершения задачи.
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();
}
}
}
Когда я запускал приложение 10 раз и не менее 3-4 раз, программа не выводила правильное количество выполненных задач. В идеале должно быть напечатано 100 (если не происходит исключений). Но в некоторых случаях это была печать 98, 99 и т. Д.
Таким образом, это доказывает, что одновременные обновления ArrayList не дадут правильных результатов.
Если я заменю ArrayList версией Synchronized , программа выдаст правильные результаты.