背景
- 我的项目中一个游戏一个线程,为了防止线程重复开启,每个线程启动后都会已房间号重命名,并在开启游戏线程前验证。
- 结果游戏结后再也开不了游戏,
- 原因是线程池回收线程时,原来设置的线程名还在线程池里面,导致每次验证线程是否存在,他都存在,不能新开游戏!
- 找了各种博客查找管理线程池的博客,有用的不多
- 解决:用return结束线程,线程结束前重新命名,为防止再次出现此问题,特用UUID 作为线程名
- 多次验证后还是偶尔出现bug,现改为放到 finally{}代码块里面,绝对保证线程结束后每次都会重命名
验证线程池回收线程时,已设置的名字的线程,回收线程名后不会改变
// 验证线程回收已设置的名字,不会改变的情况
public static void main(String[] args) {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
//配置核心线程数
executor.setCorePoolSize(1);
//配置最大线程数
executor.setMaxPoolSize(1);
//配置队列大小
// executor.setQueueCapacity(99999);
//配置线程池中的线程的名称前缀
executor.setThreadNamePrefix("Game-Executor");
/**
* rejection-policy:当pool已经达到max size的时候,如何处理新任务
* CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
*/
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.initialize();
executor.execute(() -> {
System.out.println("线程 1 开始:"+Thread.currentThread().getName());
Thread.currentThread().setName("------------测试线程-------");
System.out.println("线程 1 结束:已设置线程名字"+Thread.currentThread().getName());
});
executor.execute(() -> {
System.out.println("线程2 开始:本次线程名字是"+Thread.currentThread().getName());
// Thread.currentThread().setName("测试线程2");
// System.out.println("executor = " + "测试线程");
});
//检查程序某个线程是否在运行的代码
Map<Thread, StackTraceElement[]> allStackTraces = Thread.getAllStackTraces();
Set<Thread> threads = allStackTraces.keySet();
HashMap<String, String> temp = new HashMap<>();
for (Thread thread : threads) {
temp.put(thread.getName(), null);
}
System.out.println("temp = " + temp);
}
测试结果
检查程序某个线程是否在运行的代码
Map<Thread, StackTraceElement[]> allStackTraces = Thread.getAllStackTraces();
Set<Thread> threads = allStackTraces.keySet();
HashMap<String, String> temp = new HashMap<>();
for (Thread thread : threads) {
temp.put(thread.getName(), null);
}
if (!temp.containsKey("你设置的线程名字")) {
//一个线程
gameCountdownService.gameCountdown(requestMessage.getRoom());
}