关于AtomicInteger变量的一些疑问

本人最近写了一段代码,用到了AtomicInteger对这个变量,但是期待的结果与代码的实际运行
结果相差好大,现将代码奉上,求各位大牛给下解决方案。
class IDGeneration {
private final static ConcurrentHashMap idMap = new ConcurrentHashMap();

    private static final long baseTime = 1462377600000L;
    private Lock lock;

    IDGeneration() {
        lock = new ReentrantLock();
    }

    @SuppressWarnings("unused")
    public Long generateRelativeIncrementUniqueId(String flag) {
        String dateString = GengratedUnqueId.formatDate(new Date(),
                GengratedUnqueId.PATTERN);
        Long currentTime = (System.currentTimeMillis() - baseTime);
        AtomicInteger queueId = new AtomicInteger(0);
        int i = 0;
        Long tempValue = null;
        lock.lock();
        try {
            queueId = idMap.get(currentTime);
            if (queueId == null) {
                queueId = new AtomicInteger(0);
                idMap.clear();
                idMap.put(currentTime, queueId);
                tempValue = (currentTime << 5 | queueId.get());
            } else {
                queueId.getAndIncrement();
                idMap.put(currentTime, queueId);
                tempValue = (currentTime << 5 | queueId.get());
            }
        } finally {
            lock.unlock();
        }
        return tempValue;
        return null;
    }
}


这是测试代码:
public static void main(String[] args) throws Exception {
static ConcurrentHashMap<Long, String> map = new ConcurrentHashMap<Long, String>();

    final IDGeneration idGeneration = new IDGeneration();
    for (int i = 0; i < 100; i++) {

        Thread thread = new Thread(new Runnable() {

            @Override
            public void run() {

                long value = idGeneration
                        .generateRelativeIncrementUniqueId();
                map.put(value, "");
            }
        });
        thread.start();

    }
    TimeUnit.SECONDS.sleep(5);
    System.out.println("map.size===" + map.size());
    }

先说最早的版本:
// idMap.clear();
这行代码注释掉就可以了,少的部分其实是被你自己清除了,同步上是够了;

后面你改的,缺少同步,多线程不安全,改如下:

 public Long generateRelativeIncrementUniqueId() {
        long tempValue = (System.currentTimeMillis() - baseTime);
        long value = 0;
        AtomicInteger queueId = map.get(tempValue);
        if (queueId == null) {
            // 这里需要同步,因为map中还没有queueId
            synchronized (this) {
                // 需要再检验一遍
                queueId = map.get(tempValue);
                if (queueId == null) {
                    queueId = new AtomicInteger(0);
                    map.put(tempValue, queueId);
                }
            }
            value = (tempValue << 8 | queueId.getAndIncrement());
        } else {
            // queueId.getAndIncrement();
            // map.put(tempValue, queueId);//没必要
            value = (tempValue << 8 | queueId.getAndIncrement());
        }
        System.out.println(tempValue + "," + queueId.get());
        return value;
    }

逻辑就很大问题,全局变量和局部变量也没划分清楚,
特别: Long currentTime = (System.currentTimeMillis() - baseTime);
这个时间基本每次都不一样了,还需要缓存在idMap吗?

我简化了代码:

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class SimpleID {

private static final long baseTime = 1462377600000L;

public static void main(String[] args) throws Exception {
    final ConcurrentHashMap<Long, String> map = new ConcurrentHashMap<Long, String>();

    final SimpleID idGeneration = new SimpleID();
    for (int i = 0; i < 100; i++) {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                long value = idGeneration.generateRelativeIncrementUniqueId();
                map.put(value, "");
            }
        });
        thread.start();

    }
    TimeUnit.SECONDS.sleep(5);
    System.out.println("map.size===" + map.size());
}

private AtomicInteger queueId = new AtomicInteger(0);

public Long generateRelativeIncrementUniqueId() {
    Long tempValue = baseTime + queueId.getAndIncrement();
    return tempValue;
}

}


AtomicInteger足够了,它本身是没问题的,这样你就可以好好理解AtomicInteger了

public Long generateRelativeIncrementUniqueId() {
long tempValue = (System.currentTimeMillis() - baseTime);
long value = 0;
queueId = map.get(tempValue);
if (queueId == null) {
queueId = new AtomicInteger(0);
map.put(tempValue, queueId);
value = (tempValue << 8 | queueId.get());
} else {
queueId.getAndIncrement();
map.put(tempValue, queueId);
value = (tempValue << 8 | queueId.get());
}
System.out.println(tempValue + "," + queueId.get());
return value;
}

这是处理方法的逻辑,main方法保持不变。运行结果后:map.size===95
下边的图片是几个重复的queueId的值。

![图片说明](https://img-ask.csdn.net/upload/201606/28/1467085304_869998.png)

这是图片的部分重复数据的内容:
4707077338,0
4707077338,0
4707077338,2
4707077338,1
4707077339,0
4707077339,2
4707077339,2