我编写了一个执行4个线程的代码,每个线程将向列表中添加5000个整数。 在执行结束时,我应该在列表中包含4 * 5000个元素。 但是我最终只有1190(这个数字可能会改变)
代码在这里:
import java.util.ArrayList;
import java.util.List;
public class ConcurentList {
public static void main(String[] args) throws InterruptedException {
int range = 5000;
int nbThreads = 4;
List<Integer> integers = new ArrayList<>();
ThreadSafeArrayList<Integer> integerThreadSafeArrayList = new ThreadSafeArrayList<>(integers);
Thread[] arrayOfThread = new Thread[nbThreads];
for (int i = 0; i < nbThreads; i++)
{
arrayOfThread[i] = new Thread(() -> {
for (int j = 0; j < range; j++) {
integerThreadSafeArrayList.add(1);
}
});
arrayOfThread[i].start();
System.out.println("Le thread " + i + " ended.");
}
System.out.println("Size of the list " + integerThreadSafeArrayList.getSize());
}
}
和ThreadSafeArrayList:
import java.util.List;
public class ThreadSafeArrayList<T> {
private List<T> list;
private final Object lock = new Object();
public ThreadSafeArrayList(List<T> list) {
this.list = list;
}
public boolean add(T element) {
boolean add;
synchronized (lock) {
add = list.add(element);
}
return add;
}
public int getSize() {
return list.size();
}
}
我了解到arraylist不是线程安全的,因此可以预测执行的行为,但是由于我使用了私有最终锁上的同步,所以我希望能够获得正常的行为。
我想念什么?
答案 0 :(得分:1)
这是因为,当执行该命令时,
System.out.println("Size of the list " + integerThreadSafeArrayList.getSize());
其他线程仍在运行,并且正在执行您要求它们执行的工作。
要查看实际结果,请在最后一条语句之前添加此行。
TimeUnit.SECONDS.sleep(5);
我现在看到的输出是:
Le thread 0 ended.
Le thread 1 ended.
Le thread 2 ended.
Le thread 3 ended.
Size of the list 20000
答案 1 :(得分:1)
有2个问题:
您需要加入启动的线程,以使它们在方法主结束之前完成工作。
for (Thread thread : arrayOfThread) {
thread.join();
}
getSize方法不是线程安全的,因此您需要使用同步:
public int getSize() {
synchronized (lock) {
return list.size();
}
}
答案 2 :(得分:0)
等待结果
for (int i = 0; i < nbThreads; i++) {
arrayOfThread[i].join();
}