【发布时间】:2020-08-20 09:12:29
【问题描述】:
由于我不是专门研究多线程的,所以问题可能是低级甚至愚蠢的,请原谅=)
这是我的代码调用流程;
MessageNotificationJobExecutionConfig -> AsyncMessageNotificationJobExecutor -> NotificationJobExecutor.execute()
MessageNotificationJobExecutionConfig(查找要处理的对象)并在循环内调用 AsyncMessageNotificationJobExecutor
AsyncMessageNotificationJobExecutor 在 execute() 方法上有 @Async("messageNotificationTaskExecutor") 注释。
AsyncMessageNotificationJobExecutor.execute() 方法调用 NotificationJobExecutor.execute()
messageNotificationTaskExecutor 是 ThreadPoolTaskExecutor
的一个实例这是我的问题;
如果没有错,默认 NotificationJobExecutor 有一个 singletone 实例。
即使 AsyncMessageNotificationJobExecutor 异步工作并使用线程池任务执行器,所有线程也只调用 NotificationJobExecutor 实例(单调)。
我不确定,我可能误解了 Thread_1 调用 NotificationJobExecutor.execute() 并且在该线程完成其工作之前,其他线程等待 Thread_1。我的推断正确吗?
我认为即使它看起来是多线程,实际上它也可以单调运行
@Component("messageNotificationTaskExecutor")
public class MessageNotificationThreadPoolTaskExecutor extends ThreadPoolTaskExecutor {
@Value("${message.notification.task.executor.corePoolSize}")
Integer corePoolSize;
@Value("${message.notification.task.executor.maxPoolSize}")
Integer maxPoolSize;
@Value("${message.notification.task.executor.queueCapacity}")
Integer queueCapacity;
public MessageNotificationThreadPoolTaskExecutor() {
super();
}
@PostConstruct
public void init() {
super.setCorePoolSize(corePoolSize);
super.setMaxPoolSize(maxPoolSize);
super.setQueueCapacity(queueCapacity);
}
}
@Configuration
public class MessageNotificationJobExecutionConfig {
protected Logger log = LoggerFactory.getLogger(getClass());
@Autowired
AsyncMessageNotificationJobExecutor asyncMessageNotificationJobExecutor;
@Autowired
MessageNotificationThreadPoolTaskExecutor threadPoolTaskExecutor;
@Autowired
JobExecutionRouter jobExecutionRouter;
@Autowired
NotificationJobService notificationJobService;
private Integer operationType = OperationType.ACCOUNT_NOTIFICATION.getValue();
@Scheduled(cron = "${message.notification.scheduler.cronexpression}")
public void executePendingJobs() {
List<NotificationJob> nextNotificationJobList = notificationJobService.findNextJobForExecution(operationType, 10);
for (NotificationJob nextNotificationJob : nextNotificationJobList) {
if (threadPoolTaskExecutor.getActiveCount() < threadPoolTaskExecutor.getMaxPoolSize()) {
asyncMessageNotificationJobExecutor.execute(nextNotificationJob);
}
}
}
}
@Service
public class AsyncMessageNotificationJobExecutor {
@Autowired
NotificationJobExecutor notificationJobExecutor;
@Autowired
NotificationJobService notificationJobService;
@Async("messageNotificationTaskExecutor")
public void execute(NotificationJob notificationJob) {
notificationJobExecutor.execute(notificationJob);
}
}
@Component
public class NotificationJobExecutor implements JobExecutor {
@Override
public Integer getOperationType() {
return OperationType.ACCOUNT_NOTIFICATION.getValue();
}
@Override
public String getOperationTypeAsString() {
return OperationType.ACCOUNT_NOTIFICATION.name();
}
@Override
public void execute(NotificationJob notificationJob) {
// TODO: 20.08.2020 will be execute
}
}
【问题讨论】:
-
他们不会等待,你的课堂上没有任何同步。所以允许多个线程调用同一个实例。某物是单例的事实并不意味着一次有 1 个线程可以访问该对象。您的示例过于复杂且令人费解,它已经安排了调用异步方法的内容。所以它是异步的两次。你也不需要子类。
标签: java multithreading spring-boot