import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
public class Test {
public static void main(String[] args) {
int threadCount = 10;
int cap = 1000 * threadCount;
Map<String, Integer> unsafeMap = new HashMap<>(cap);
Map<String, Integer> safeMap = new Hashtable<>(cap);
for (int i = 0; i < threadCount; i++) {
/*
safeMap早于unsafeMap启动结果:
safeMap = 10000
unsafeMap = 小于10000
unsafeMap早于safeMap启动结果:
safeMap = 9500
unsafeMap = 小于10000
*/
new Runner(unsafeMap).start();
new Runner(safeMap).start();
}
while(Thread.activeCount() > 2){
Thread.yield();
}
System.out.println("safeMap = " + safeMap.size());
System.out.println("unsafeMap = " + unsafeMap.size());
}
}
class Runner extends Thread {
Map map;
Runner(Map map) {
this.map = map;
}
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
map.put(this.getName() + i, i);
}
}
}
请问,Hashtable后启动线程时,上限稳定在9500是什么原因导致的,感谢各位大佬~
补充:我试了线程数,threadCount的个位是1-5时没有问题(比如1,12,23等等),个位6-0(比如7,16,29等等),每增加1条,总数就少100,所以10条线程9500,期待大佬贴源码解惑,感激不尽~
恭喜您!发现了新大陆,这就是传说中的线程不安全并发导致的库存超卖问题;
原理:
两个线程同时运行到map.put(key,value),第一个线程获取到了下一个保存点,第二个线程也获取到了下一个保存点,第一个线程用下一个保存点存了key-value,第二个线程也用下一个保存点存了key-value,结果下一个保存点就职存了第二个线程的key-value,所以就少了一个,以此类推,就会出现好几个,线程越多,少的越多