Spring 任务异步和延迟

问题描述 投票:0回答:4

我需要做一件我不知道哪一个是最佳实践的事情。

在我向特定服务发送一个请求后,该请求返回 OK 并将我的请求排队。我有一个回调服务,用于在结束时通知。

问题是整个过程可能需要很长时间并且没有任何通知,之后我需要考虑超时。

该应用程序是SpringBoot APP,我正在考虑在具有睡眠时间的服务方法上使用注释@EnableAsync和@Async。

@Configuration
@EnableAsync
public class AsyncConfiguration implements AsyncConfigurer {

    @Override
    public Executor getAsyncExecutor() {
        
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(2);
        executor.setMaxPoolSize(10);
        executor.setQueueCapacity(500);
        executor.setThreadNamePrefix("TIMCLL-");
        executor.initialize();
        return executor;
        
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        // TODO Auto-generated method stub
        return null;
    }

}

。 。 .

@Async
public void verifyStatusTimPayment() throws InterruptedException {
    
    Thread.sleep(5000);
    logger.info( "Executed after 5s " +  new SimpleDateFormat("dd/MM/yyyy hh:mm:ss").format(new Date())); 
    
}

验证需要在请求后 15 分钟内完成,并且每个请求只能进行一次。

如何在不进行 Thread.sleep 的情况下做到这一点?

java spring asynchronous task
4个回答
10
投票

可以使用ScheduledExecutorService来安排任务

ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
...
scheduler.schedule(() -> {yourtaskhere}, 15, TimeUnit.MINUTES);

但是这不是你想要的。如果服务器在任务调度和执行之间挂掉了怎么办?你会失去你的任务。 如果您将消息保存在队列中并稍后检索它,或者使用任何使用持久性的调度程序(a la Quartz),那就更好了


2
投票

您可以在配置中添加@EnableScheduling注释:

@Configuration
@EnableAsync
@EnableScheduling
public class AsyncConfiguration implements AsyncConfigurer {

    @Override
    public Executor getAsyncExecutor() {

        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(2);
        executor.setMaxPoolSize(10);
        executor.setQueueCapacity(500);
        executor.setThreadNamePrefix("TIMCLL-");
        executor.initialize();
        return executor;

    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        // TODO Auto-generated method stub
        return null;
    }

}

如果你想调度一次并延迟,你可以调用taskScheduler:

@Autowired 
private TaskScheduler taskScheduler;

并执行任务:

taskScheduler.schedule(
    () -> {//your task}, 
    //Your Delay task
);

1
投票

我认为我们可以在最近的春天使用@Scheduled。每 15 分钟运行一次 like方法注释如下

@Scheduled(cron = "0 0/15 * * * *")
public void verifyStatusTimPayment() throws InterruptedException {
    logger.info( "Executed after 5s " +  new SimpleDateFormat("dd/MM/yyyy hh:mm:ss").format(new Date())); 

}

我知道我迟到了,但可能会帮助正在经历线程的人


1
投票

您可以使用 Redis 支持的延迟调度程序,这将保证您不会丢失任务。这可以使用 Rqueue 非常轻松地完成。

在 Rqueue 中,您可以将 15 分钟后运行的任务排入队列,如下所示:

public class Verification { private String id; } @Component class VerificationListener { @RqueueListener( value = "verification-queue") public void onMessage(Verification verification) { // do verification } } @Service class DelayedTaskService { @Autowired private RqueueMessageSender rqueueMessageSender public void enqeueVerification(Verification verification) { rqueueMessageSender.enqueuIn("verification-queue", verification, Duration.ofMinutes(15); } }

附注我是 Rqueue 库的开发人员。

© www.soinside.com 2019 - 2024. All rights reserved.