lcx_1989210 2016-06-27 11:27 采纳率: 33.3%
浏览 1703
已采纳

关于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());
    }
  • 写回答

5条回答 默认 最新

  • _1_1_7_ 2016-06-29 01:18
    关注

    先说最早的版本:
    // 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;
        }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(4条)

报告相同问题?

悬赏问题

  • ¥20 5037端口被adb自己占了
  • ¥15 python:excel数据写入多个对应word文档
  • ¥60 全一数分解素因子和素数循环节位数
  • ¥15 ffmpeg如何安装到虚拟环境
  • ¥188 寻找能做王者评分提取的
  • ¥15 matlab用simulink求解一个二阶微分方程,要求截图
  • ¥30 乘子法解约束最优化问题的matlab代码文件,最好有matlab代码文件
  • ¥15 写论文,需要数据支撑
  • ¥15 identifier of an instance of 类 was altered from xx to xx错误
  • ¥100 反编译微信小游戏求指导