我们拥有先进的人力资源系统,该系统有一项服务计算员工出勤率,如果计算员工(X,Y,Z),它必须遵循以下内容,它会打开3个线程并并行计算,但如果请求计算员工数据X 在上一次计算结束之前再次必须推迟,直到上一个线程计算员工 X 的数据完成。
ScheduleWeekAttendanceBean scheduleWeekAttendanceBean = null;
ThreadPoolExecutor threadPoolExecutor = employeeThreadPoolExecutorMap.get(employmentBean.id);
if (threadPoolExecutor == null || threadPoolExecutor.isTerminating() || threadPoolExecutor.isTerminated()) {
threadPoolExecutor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), new RejectedExecutionHandlerImpl());
employeeThreadPoolExecutorMap.put(employmentBean.id, threadPoolExecutor);
ThreadPoolTaskExecutorMonitorService threadPoolTaskExecutorMonitorService = new ThreadPoolTaskExecutorMonitorService(threadPoolExecutor, "#" + employmentBean.employeeId);
Thread thread = new Thread(threadPoolTaskExecutorMonitorService);
thread.start();
}
AttendanceBuilder attendanceBuilder = (AttendanceBuilder) AppContext.getBean("attendanceBuilder");
attendanceBuilder.initialize(employmentBean, selectedDate);
Future<ScheduleWeekAttendanceBean> future = threadPoolExecutor.submit(attendanceBuilder);
scheduleWeekAttendanceBean = future.get();
if (threadPoolExecutor.getActiveCount() == 0) {
employeeThreadPoolExecutorMap.remove(employmentBean.id);
threadPoolExecutor.shutdownNow();
}
return scheduleWeekAttendanceBean;
这里发生了什么,它一一处理它们,我需要实现这个逻辑,但只有在 map 中存在相同的员工时才会阻止。
最佳答案
为每个员工 ID 创建单独的 ThreadPoolExecutor 会产生开销。每个ThreadPoolExecutor
都包含一个Thread
,该线程会消耗大量内存,这可能会导致致命的OutOfMemoryError
。因此,我建议改用 SerialExecutor
,这在 java.util.concurrent.Executor 的文档中进行了描述。 。 SerialExecutor
不包含线程,而是使用外部 Executor
。您可以为所有 SerialExecutor
创建单个 Executor
,并调整其配置(线程数)。由于 SerialExecutor
很小,因此您可以将它们全部永久保留在 employeeThreadPoolExecutorMap
中。
另一种方法是使用 Actors而不是执行者。 Actor 可以被视为专门的 Executor,旨在处理特定任务(消息)。你可以使用Akka actor,或者我的Simple Actor .
关于java - 如何管理ThreadPoolTaskExecutor来阻止某些请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58890287/