麻烦分析一下原因,下面贴了代码,具体操作和结果在注释中做了介绍。

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,所以就少了一个,以此类推,就会出现好几个,线程越多,少的越多