在多线程中输出时间戳是否会重复
在多线程中,以时间戳为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位的微秒为单位的.