1

@Scheduled我对一起使用 Spring和@Async功能有一些疑问。

假设我的要求是每 1 秒处理来自数据库的 5 行,因此在调度程序线程的 1 次传递中将创建 5 个异步线程来处理数据库中的每一行。

我的问题如下:

1)是否有另一种方法来创建 5 个 ascynchonis 线程,而不是在预定方法中使用 while 循环?

我看到这种方法的一个问题是线程池活动计数可能不等于最大池大小,因此循环不会在 1 秒过去之前中断。

2) 在某些情况下,AsyncService 中的日志语句 ieExecuting dbItem on the following asyncExecutor : task-scheduler-1显示 task-scheduler-1为线程名称,而不是async_thread_我一直期望的?

3) 如果我的调度程序线程运行时间超过 1 秒,调度程序的后续通过会发生什么?

异步执行器:

@Override
@Bean(name="asyncExecutor")
public Executor getAsyncExecutor() {
    ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor();        
    threadPoolTaskExecutor.setCorePoolSize(5);
    threadPoolTaskExecutor.setQueueCapacity(5);
    threadPoolTaskExecutor.setMaxPoolSize(10);
    threadPoolTaskExecutor.setThreadNamePrefix("async_thread_");
    threadPoolTaskExecutor.setWaitForTasksToCompleteOnShutdown(true);     
    return threadPoolTaskExecutor;
}

它被注入到具有预定方法的类中:

@Autowired
@Qualifier("asyncExecutor")
private ThreadPoolTaskExecutor threadPoolTaskExecutor;

@Autowired
AsyncService asyncService;

@Autowired
private DaoService daoService;

@Scheduled(fixedRateString = "1000")
public void schedulerMetod() {

    try {       

        while (threadPoolTaskExecutor.getActiveCount() < threadPoolTaskExecutor.getMaxPoolSize()) {
            DbItem dbItem = daoService.retrieveNewItemFromDB();         
            if (dbItem != null){            
                asyncService.processNewItem(dbItem);
            }
        }

    } catch (ObjectOptimisticLockingFailureException ole){
        log.info(ole.getMessage());     
    } catch (Exception ex){
        log.error(ex.getMessage());
    }   
}


@Service
public class AsyncServiceImpl implements AsyncService {

    @Autowired
    private TaskService taskService;

    @Override
    @Transactional
    @Async("asyncExecutor")
    public void processNewItem(DbItem dbItem) {
        log.debug("Executing dbItem on the following asyncExecutor : " + Thread.currentThread().getName());     
        taskService.processNewItem(dbItem); 
    }

}
4

1 回答 1

0

使用ThreadPoolTaskSchedulerbean 您将有双重目的,因为它同时实现了TaskExecutor(supports @Async) 和TaskScheduler(supports @Scheduled) 接口。你可以这样配置:

@Bean
public ThreadPoolTaskScheduler taskScheduler() {
    ThreadPoolTaskScheduler threadPoolTaskScheduler = new ThreadPoolTaskScheduler();
    threadPoolTaskScheduler.setPoolSize(5);
    threadPoolTaskScheduler.setThreadNamePrefix("async_thread_");
    threadPoolTaskScheduler.initialize();
    return threadPoolTaskScheduler;
}

如果您提供另一个执行器名称,例如taskScheduler1then 您应该提供执行器名称作为@Async("taskScheduler1"). 通过这种实现,您已经有了问题 1 和 2 的答案。

关于您的第三个问题,如果您的线程池中的所有线程都很忙,那么您的调度程序在线程释放之前什么都不做,然后它会执行调度任务。你可能会想给线程池一个更大的尺寸。

最后但同样重要的是,仅使用 of@Scheduled就足够了,因为它是异步工​​作的。

于 2019-01-08T08:17:25.627 回答