有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

SpringBoot中的java单线程和多线程。真的是多线程吗?

因为我不是专门研究多线程,所以问题可能是低级的,甚至是愚蠢的,请原谅=)

下面是我的代码调用流程图

MessageNotificationJobExecutionConfig->;AsyncMessageNotificationJobExecutor->;通知作业执行器。执行()

MessageNotificationJobExecutionConfig(查找要处理的对象)并在循环内调用AsyncMessageNotificationJobExecutor

AsyncMessageNotificationJobExecutor在execute()方法上有@Async(“messageNotificationTaskExecutor”)注释

AsyncMessageNotificationJobExecutor。execute()方法调用NotificationJobExecutor。执行()

messageNotificationTaskExecutorThreadPoolTaskExecutor

这是我的问题

如果我没有错,默认情况下,通知JobExecutor有一个单音实例

即使AsyncMessageNotificationJobExecutor异步工作并使用线程池任务执行器,所有线程都只调用NotificationJobExecutor实例(单音)

我不确定,我可能会误解线程1调用NotificationJobExecutor。execute(),直到该线程完成其任务,其他线程等待线程\u 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) 个答案

  1. # 1 楼答案

    在您创建的场景中,您拥有所有单例实例。但是流看起来是这样的:

    1. MessageNotificationJobExecutionConfig中调用executePendingJobs
    2. 按顺序迭代每个NotificationJob(因此这是等待)
    3. 调用AsyncMessageNotificationJobExecutor中的execute,这将向线程池中的messageNotificationTaskExecutor顺序(从而阻塞)添加执行
    4. 在单独的线程中执行步骤3中创建的作业(因此这实际上执行AsyncMessageNotificationJobExecutor中的方法)
    5. NotificationJobExecutor中的execute方法的阻塞调用

    “神奇”发生在步骤3中,Spring将向messageNotificationTaskExecutor添加一个作业,而不是执行方法,该作业将封装对步骤4的调用。这导致对步骤4的调用是异步的,因此对同一实例的多个调用可以同时发生。因此,请确保此对象是无状态的