解决方案 »

  1.   

    thread2个,get4次,空指针异常了
      

  2.   

    新建两个线程,实际存在三个线程,Main线程执行完之后,threadMap自动回收。此时threadMap == null   传入子线程的地址也就指向Null。
      

  3.   

    ThreadMap不是main函数里的局部变量,为什么main执行完了之后会被回收呢???
      

  4.   

    我试了在main函数的最后加了Thread.sleep(1000);还是会有时报这个错,报错的时候main线程还没有执行完。估计不是这个原因。
      

  5.   

    线程安全。
    换成线程安全map。public static ConcurrentMap<Thread, Integer> map = new ConcurrentHashMap<Thread, Integer>();
      

  6.   

    由于HashMap是非线程安全的,两个线程同时写入值时,可能相互覆盖。
    报错中的空指针,是由于从map中取到的value为null,在自动解箱转为int时,抛出了空指针异常。当两个线程对象的hash值同时分配到map的同一个桶时,如下代码如果同时执行,只会保留后一个线程的值。
    测试的结果也验证了分析,报错时,hash后的值在同一个桶中。
            /**
     * Adds a new entry with the specified key, value and hash code to the
     * specified bucket. It is the responsibility of this method to resize the
     * table if appropriate.
     * 
     * Subclass overrides this to alter the behavior of put method.
     */
    void addEntry(int hash, K key, V value, int bucketIndex) {
    Entry<K, V> e = table[bucketIndex];
    table[bucketIndex] = new Entry<K, V>(hash, key, value, e);//同时执行,后执行的线程覆盖前面写入的
    if (size++ >= threshold)
    resize(2 * table.length);
    }package net.jcip.test;import java.util.HashMap;
    import java.util.Map;
    import java.util.Random;public class ThreadScopeShareData {
    private static Map<Thread, Integer> threadMap = new HashMap<Thread, Integer>(); public static void main(String[] args) {
    for (int i = 0; i < 2; i++) {
    new Thread(new Runnable() {
    @Override
    public void run() {
    int data = new Random().nextInt();
    System.out.println(indexFor(hash(Thread.currentThread()
    .hashCode()), 16));
    System.out.println(Thread.currentThread().getName()
    + " has put data: " + data);
    threadMap.put(Thread.currentThread(), data);
    new A().get();
    new B().get();
    } }).start();
    } } static class A {
    public void get() {
    System.out.println(Thread.currentThread() + " threadMap= "
    + threadMap);
    int data = threadMap.get(Thread.currentThread());
    System.out.println("from A " + Thread.currentThread().getName()
    + " get data: " + data);
    }
    } static class B {
    public void get() {
    int data = threadMap.get(Thread.currentThread());
    System.out.println("from B " + Thread.currentThread().getName()
    + " get data: " + data);
    }
    } static int hash(int h) {
    h ^= (h >>> 20) ^ (h >>> 12);
    return h ^ (h >>> 7) ^ (h >>> 4);
    } /**
     * Returns index for hash code h.
     */
    static int indexFor(int h, int length) {
    return h & (length - 1);
    }
    }
    14
    Thread-1 has put data: 1593710152
    14
    Thread-0 has put data: 1594094901
    Thread[Thread-0,5,main] threadMap= {Thread[Thread-0,5,main]=1594094901}
    from A Thread-0 get data: 1594094901
    Thread[Thread-1,5,main] threadMap= {Thread[Thread-0,5,main]=1594094901}
    from B Thread-0 get data: 1594094901
    Exception in thread "Thread-1" java.lang.NullPointerException
    at net.jcip.test.ThreadScopeShareData$A.get(ThreadScopeShareData.java:34)
    at net.jcip.test.ThreadScopeShareData$1.run(ThreadScopeShareData.java:21)
    at java.lang.Thread.run(Unknown Source)