在多线程中输出时间戳是否会重复

在多线程场景中,使用System.currentTimeMillis()作为HashMap的键可能导致键重复,因时间戳在毫秒级别可能相同。这会导致数据覆盖。建议使用System.nanoTime()或UUID生成唯一标识以避免冲突。示例代码展示了这个问题并提供了修复方法。
摘要由CSDN通过智能技术生成

在多线程中输出时间戳是否会重复

在多线程中,以时间戳为key,存入map,使用完毕后删除.会不会报错. 会
因为使用System.currentTimeMillis()的结果是13位的,属于(毫秒级别),但是多线程的执行会小于毫秒,会造成多个线程中,产生的时间戳是一样的.
建议使用uuid或者 System.nanoTime()

线程池配置

package com.cloudskysec.operation.config;

import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import javax.annotation.PreDestroy;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

/**
 *
 */
@Configuration
@EnableAsync
public class NewThreadPoolConfig {

    @Bean("xyqThreadPoolTaskExecutor")
    @ConditionalOnMissingBean(name = "xyqThreadPoolTaskExecutor")
    public Executor xyqThreadPoolTaskExecutor() {
        System.out.println("==================xyqThreadPoolTaskExecutor开启==================");
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 核心线程池大小
        executor.setCorePoolSize(10);
        // 最大线程池大小
        executor.setMaxPoolSize(50);
        // 队列容量
        executor.setQueueCapacity(100);
        // 线程池维护线程所允许的空闲时间
        executor.setKeepAliveSeconds(60);
        // 线程名称前缀
        executor.setThreadNamePrefix("xyq-");
        // 拒绝策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 初始化线程池
        executor.initialize();
        return executor;
    }

    @PreDestroy
    public void shutdownThreadPoolExecutor() {
        ThreadPoolTaskExecutor executor = (ThreadPoolTaskExecutor) xyqThreadPoolTaskExecutor();
        executor.shutdown();
        System.out.println("==================xyqThreadPoolTaskExecutor关闭==================");
    }
}

业务使用

可以做一个测试业务来看看

package com.cloudskysec.operation.controller;

import com.cloudskysec.commons.core.core.domain.AjaxResult;
import com.cloudskysec.commons.core.utils.UUIDUtils;
import com.cloudskysec.operation.utils.ExecUtils;
import com.jcraft.jsch.JSchException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.scheduling.annotation.Async;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;

/**
 * @author : xuyanqiang
 * @date : 2023/4/17
 */
@RestController
@RequestMapping("/TestControllerII")
public class TestControllerII {

    @Autowired
    @Qualifier("xyqThreadPoolTaskExecutor")
    private Executor xyqThreadPoolTaskExecutor;

    /**
     * 存放ssh连接信息的map
     */
    public static Map<String, Object> execSshMap = new ConcurrentHashMap<>();


    @GetMapping("/testMethodI")
    public AjaxResult testMethodI(@RequestParam Map<String, Object> param) throws Exception {
        String codeValue = (String) param.get("codeValue");
        Map<String, Object> resultMap = this.testMethodCommon(codeValue);
        return AjaxResult.error("OK", resultMap);
    }

    @Async("xyqThreadPoolTaskExecutor")
    public Map<String, Object> testMethodCommon(String codeValue) throws Exception {
        Map<String, Object> resultMap = new HashMap<>();
        int subThreadNum = 10;

        CountDownLatch countDownLatch = new CountDownLatch(subThreadNum);
        for (int i = 0; i < subThreadNum; i++) {
            String uuid = UUIDUtils.getUUID();

            xyqThreadPoolTaskExecutor.execute(() -> {
                String Key = System.currentTimeMillis() + "";
                System.out.println(Key);

                // 添加
                execSshMap.put(Key, codeValue + uuid);

                // 等待
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                System.out.println(execSshMap.toString());
                countDownLatch.countDown();

            });
        }
        countDownLatch.await(6000, TimeUnit.SECONDS);
        return resultMap;
    }
}
1682409421290
1682409421290
1682409421290
1682409421290
1682409421290
1682409421290
1682409421290
1682409421290
1682409421290
1682409421290
{1682409421290=3232323236188d79f48f40c4948a2d0c9f5e82ce}
{1682409421290=3232323236188d79f48f40c4948a2d0c9f5e82ce}
{1682409421290=3232323236188d79f48f40c4948a2d0c9f5e82ce}
{1682409421290=3232323236188d79f48f40c4948a2d0c9f5e82ce}
{1682409421290=3232323236188d79f48f40c4948a2d0c9f5e82ce}
{1682409421290=3232323236188d79f48f40c4948a2d0c9f5e82ce}
{1682409421290=3232323236188d79f48f40c4948a2d0c9f5e82ce}
{1682409421290=3232323236188d79f48f40c4948a2d0c9f5e82ce}
{1682409421290=3232323236188d79f48f40c4948a2d0c9f5e82ce}
{1682409421290=3232323236188d79f48f40c4948a2d0c9f5e82ce}

造成这样的原因:
因为在多线程中使用的时间戳是一样的,key也就一样了.在等待的两秒.value值就由最后一个代替了.如果我们的value是封装对象的话,就会造成对象错误.
解决:

// String Key = System.currentTimeMillis() + "";
   String Key = System.nanoTime() + "";
   或者
   String Key = UUIDUtils.getUUID();
257968451921600
257968451958600
257968452054200
257968451859700
257968451857600
257968452028600
257968451992900
257968451777900
257968451948800
257968451765600
{257968452028600=32323232a882b12f4e78441788d85305ca207823, 257968451777900=3232323232ae1cf611714c8693425e5206584374, 257968451765600=3232323270357746ac2248c1b92bdef458945104, 257968451958600=32323232909868a86c3e44cfacc0bdb02d8e93fe, 1682409421290=3232323236188d79f48f40c4948a2d0c9f5e82ce, 257968451859700=323232323459d2eeb7b040eb90091dd8b46e26b3, 257968451857600=323232324db21b7bdbd74540a7e377e4201a38ed, 257968451921600=323232325dd811e648cf49a2a04a61849d46ce65, 257968452054200=323232324cb467aa39bb40169c31acb90658290b, 257968451992900=323232329c9edb74456040358bc1e1e04877ab2b, 257968451948800=323232324957703a33db44319f5970f2f32c2eb7}
{257968452028600=32323232a882b12f4e78441788d85305ca207823, 257968451777900=3232323232ae1cf611714c8693425e5206584374, 257968451765600=3232323270357746ac2248c1b92bdef458945104, 257968451958600=32323232909868a86c3e44cfacc0bdb02d8e93fe, 1682409421290=3232323236188d79f48f40c4948a2d0c9f5e82ce, 257968451859700=323232323459d2eeb7b040eb90091dd8b46e26b3, 257968451857600=323232324db21b7bdbd74540a7e377e4201a38ed, 257968451921600=323232325dd811e648cf49a2a04a61849d46ce65, 257968452054200=323232324cb467aa39bb40169c31acb90658290b, 257968451992900=323232329c9edb74456040358bc1e1e04877ab2b, 257968451948800=323232324957703a33db44319f5970f2f32c2eb7}
{257968452028600=32323232a882b12f4e78441788d85305ca207823, 257968451777900=3232323232ae1cf611714c8693425e5206584374, 257968451765600=3232323270357746ac2248c1b92bdef458945104, 257968451958600=32323232909868a86c3e44cfacc0bdb02d8e93fe, 1682409421290=3232323236188d79f48f40c4948a2d0c9f5e82ce, 257968451859700=323232323459d2eeb7b040eb90091dd8b46e26b3, 257968451857600=323232324db21b7bdbd74540a7e377e4201a38ed, 257968451921600=323232325dd811e648cf49a2a04a61849d46ce65, 257968452054200=323232324cb467aa39bb40169c31acb90658290b, 257968451992900=323232329c9edb74456040358bc1e1e04877ab2b, 257968451948800=323232324957703a33db44319f5970f2f32c2eb7}
{257968452028600=32323232a882b12f4e78441788d85305ca207823, 257968451777900=3232323232ae1cf611714c8693425e5206584374, 257968451765600=3232323270357746ac2248c1b92bdef458945104, 257968451958600=32323232909868a86c3e44cfacc0bdb02d8e93fe, 1682409421290=3232323236188d79f48f40c4948a2d0c9f5e82ce, 257968451859700=323232323459d2eeb7b040eb90091dd8b46e26b3, 257968451857600=323232324db21b7bdbd74540a7e377e4201a38ed, 257968451921600=323232325dd811e648cf49a2a04a61849d46ce65, 257968452054200=323232324cb467aa39bb40169c31acb90658290b, 257968451992900=323232329c9edb74456040358bc1e1e04877ab2b, 257968451948800=323232324957703a33db44319f5970f2f32c2eb7}
{257968452028600=32323232a882b12f4e78441788d85305ca207823, 257968451777900=3232323232ae1cf611714c8693425e5206584374, 257968451765600=3232323270357746ac2248c1b92bdef458945104, 257968451958600=32323232909868a86c3e44cfacc0bdb02d8e93fe, 1682409421290=3232323236188d79f48f40c4948a2d0c9f5e82ce, 257968451859700=323232323459d2eeb7b040eb90091dd8b46e26b3, 257968451857600=323232324db21b7bdbd74540a7e377e4201a38ed, 257968451921600=323232325dd811e648cf49a2a04a61849d46ce65, 257968452054200=323232324cb467aa39bb40169c31acb90658290b, 257968451992900=323232329c9edb74456040358bc1e1e04877ab2b, 257968451948800=323232324957703a33db44319f5970f2f32c2eb7}
{257968452028600=32323232a882b12f4e78441788d85305ca207823, 257968451777900=3232323232ae1cf611714c8693425e5206584374, 257968451765600=3232323270357746ac2248c1b92bdef458945104, 257968451958600=32323232909868a86c3e44cfacc0bdb02d8e93fe, 1682409421290=3232323236188d79f48f40c4948a2d0c9f5e82ce, 257968451859700=323232323459d2eeb7b040eb90091dd8b46e26b3, 257968451857600=323232324db21b7bdbd74540a7e377e4201a38ed, 257968451921600=323232325dd811e648cf49a2a04a61849d46ce65, 257968452054200=323232324cb467aa39bb40169c31acb90658290b, 257968451992900=323232329c9edb74456040358bc1e1e04877ab2b, 257968451948800=323232324957703a33db44319f5970f2f32c2eb7}
{257968452028600=32323232a882b12f4e78441788d85305ca207823, 257968451777900=3232323232ae1cf611714c8693425e5206584374, 257968451765600=3232323270357746ac2248c1b92bdef458945104, 257968451958600=32323232909868a86c3e44cfacc0bdb02d8e93fe, 1682409421290=3232323236188d79f48f40c4948a2d0c9f5e82ce, 257968451859700=323232323459d2eeb7b040eb90091dd8b46e26b3, 257968451857600=323232324db21b7bdbd74540a7e377e4201a38ed, 257968451921600=323232325dd811e648cf49a2a04a61849d46ce65, 257968452054200=323232324cb467aa39bb40169c31acb90658290b, 257968451992900=323232329c9edb74456040358bc1e1e04877ab2b, 257968451948800=323232324957703a33db44319f5970f2f32c2eb7}
{257968452028600=32323232a882b12f4e78441788d85305ca207823, 257968451777900=3232323232ae1cf611714c8693425e5206584374, 257968451765600=3232323270357746ac2248c1b92bdef458945104, 257968451958600=32323232909868a86c3e44cfacc0bdb02d8e93fe, 1682409421290=3232323236188d79f48f40c4948a2d0c9f5e82ce, 257968451859700=323232323459d2eeb7b040eb90091dd8b46e26b3, 257968451857600=323232324db21b7bdbd74540a7e377e4201a38ed, 257968451921600=323232325dd811e648cf49a2a04a61849d46ce65, 257968452054200=323232324cb467aa39bb40169c31acb90658290b, 257968451992900=323232329c9edb74456040358bc1e1e04877ab2b, 257968451948800=323232324957703a33db44319f5970f2f32c2eb7}
{257968452028600=32323232a882b12f4e78441788d85305ca207823, 257968451777900=3232323232ae1cf611714c8693425e5206584374, 257968451765600=3232323270357746ac2248c1b92bdef458945104, 257968451958600=32323232909868a86c3e44cfacc0bdb02d8e93fe, 1682409421290=3232323236188d79f48f40c4948a2d0c9f5e82ce, 257968451859700=323232323459d2eeb7b040eb90091dd8b46e26b3, 257968451857600=323232324db21b7bdbd74540a7e377e4201a38ed, 257968451921600=323232325dd811e648cf49a2a04a61849d46ce65, 257968452054200=323232324cb467aa39bb40169c31acb90658290b, 257968451992900=323232329c9edb74456040358bc1e1e04877ab2b, 257968451948800=323232324957703a33db44319f5970f2f32c2eb7}
{257968452028600=32323232a882b12f4e78441788d85305ca207823, 257968451777900=3232323232ae1cf611714c8693425e5206584374, 257968451765600=3232323270357746ac2248c1b92bdef458945104, 257968451958600=32323232909868a86c3e44cfacc0bdb02d8e93fe, 1682409421290=3232323236188d79f48f40c4948a2d0c9f5e82ce, 257968451859700=323232323459d2eeb7b040eb90091dd8b46e26b3, 257968451857600=323232324db21b7bdbd74540a7e377e4201a38ed, 257968451921600=323232325dd811e648cf49a2a04a61849d46ce65, 257968452054200=323232324cb467aa39bb40169c31acb90658290b, 257968451992900=323232329c9edb74456040358bc1e1e04877ab2b, 257968451948800=323232324957703a33db44319f5970f2f32c2eb7}

总结

这个问题虽然说是一个很简单的bug,但是排查的时候很难发现.
我们在线程中使用随机数时,最好的是使用uuid,不要使用时间戳.或者使用15位的微秒为单位的.
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值