使用Spring Boot可以运行长时间的任务吗?

6
我想使用TaskExecutor在Spring Boot中运行几个长时间任务。我想要多个RFID读取器持续运行并获取商品标签。然后,我需要使用这些标签来更新数据库。迄今为止,我无法使用Spring Boot多次运行任务。这是否可能?
我正在创建@Component reader类。创建时,我启动监听服务和监听器以跟踪标签。我有startMessageService和setReaderConfig方法。第一个方法我启动消息监听器服务以接收来自阅读器的带有标签信息的消息。第二个方法设置阅读器以自主阅读,因此当标签经过阅读器时,阅读器会向监听器发送消息,我会收到消息。
run方法基本上使阅读器保持运行以在消息到达时进行阅读。但是由于某种原因,代码没有按照我的意愿工作。一旦读卡器有标签通过,我应该收到一条消息,但我没有收到。
底部是我的threadpooltaskexecutor bean。
我不确定我缺少什么。
@Component
@Scope("prototype")
public class AlienReader extends AlienClass1Reader implements 
TagTableListener, MessageListener, Runnable{
 private String ipaddress;
 private int port;
 private String username;
 private String password;
 int serviceport;

public AlienReader(String ipaddress, int port, String username, String pwd, 
int serviceport) throws UnknownHostException, AlienReaderException, 
InterruptedException{
    super(ipaddress, port);
    this.ipaddress=ipaddress;
    this.port=port;
    this.username=username;
    this.password=pwd;
    this.serviceport=serviceport;
    startMessageService();
    setReaderConfig();

}

}

@Bean
public ThreadPoolTaskExecutor threadPoolTaskExecutor(){
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(15);
    executor.setMaxPoolSize(42);
    executor.setQueueCapacity(11);
    executor.setThreadNamePrefix("threadPoolExecutor-");
    executor.setWaitForTasksToCompleteOnShutdown(true);
    executor.initialize();
    return executor;
}

1
一切皆有可能。展示代码,我们会提供帮助。 - Sneh
1个回答

5

Spring Boot没有任何限制;如果您能用Java或其他语言实现,那么使用Java + Spring Boot也应该可以实现。

什么是Spring Boot

需要明确的是,Spring Boot基本上只是一个构建Spring项目的框架,这些项目在历史上非常复杂,并且有很多样板代码。您可以创建Spring Boot命令行应用程序或Web应用程序(更常见)。我相信还会出现更多的选项。

因此,Spring Boot将通过轻松公开应用程序中的配置文件、自动连接所有Spring bean、设置控制器的连接等方式为您提供一个快速入门的机会。但它不会限制您编写的代码;它只是减少了其中的一部分。

你的问题

您可以使用执行器服务来运行任意数量的长时间运行任务,只要您的PC/服务器能够处理它们。

以下是一个可行的Spring Boot示例,可以并行地运行两个不同的任务一分钟。它们可以永远持续并且可以执行任何操作,而且您可以轻松地将其扩展到数百个任务。

import org.apache.catalina.core.ApplicationContext;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;

@SpringBootApplication
public class App {

    public static void main(String[] args) {
        ConfigurableApplicationContext run = SpringApplication.run(App.class, args);
        App app = run.getBean(App.class);
        app.run();
    }

    private void run() {
        Runnable r1 = () -> {
            for(int i = 0; i < 30; ++i) {
                System.out.println("task 1");
                try {Thread.sleep(1000);} catch(Exception ignored) {}
            }
        };

        Runnable r2 = () -> {
            for(int i = 0; i < 30; ++i) {
                System.out.println("task 2");
                try {Thread.sleep(1000);} catch(Exception ignored) {}
            }
        };

        //Create an executor service with 2 threads (it can be like 50
        //if you need it to be).  Submit our two tasks to it and they'll
        //both run to completion (or forever if they don't end).
        ExecutorService service = Executors.newFixedThreadPool(2);
        service.submit(r1);
        service.submit(r2);

        //Wait or completion of tasks (or forever).
        service.shutdown();
        try { service.awaitTermination(Integer.MAX_VALUE, TimeUnit.DAYS); }
        catch (InterruptedException e) { e.printStackTrace(); }
    }
}

更多信息

  • 如果您需要最终获取结果并等待结果,可以调度可调用对象而不是可运行对象。
  • 如果需要定期任务以及长时间运行的任务,有许多变种的执行器服务可供选择。
  • 您可以使用所需的任何线程数;只需增加10个即可 :)。
  • 这个特定的应用程序可能更适合作为命令行应用程序 - 但我将其制作成了正常的Spring Boot Web类型,以防您需要控制器/等来提供任务检查端点等。但对于任务本身,这些都不太相关。除非添加System.exit(),否则此应用程序不会在完成后终止,因为它希望成为长寿的Web应用程序。

2
也许更好的做法是用Spring的ApplicationRunnerCommandLineRunner bean替换Java中的public static void main方法(以便与问题保持一致)。 - Max Farsikov
没错,假设他已经有一个正在运行的应用程序,但这是回顾中非常好的一点:)。等我接近电脑时,稍后或明天我会提供一个。 - John Humphreys
@MaxFarsikov - 这里有一个完整的例子。 - John Humphreys
谢谢!这个很有效。但是现在当我运行我的代码时,我收到错误信息,因为它一直尝试重新启动消息服务。我该如何只启动一次消息服务? - Roro
那是一个不同的问题,需要你提供更多的代码等信息。请在此接受答案并打开一个新的问题,附上错误和你的任务代码(尽可能简化以重现错误),人们会在那里帮助你。也可以在这里链接它,让大家都能看到。 - John Humphreys
谢谢!我已经接受了一个答案,这是我的新问题:https://stackoverflow.com/questions/52120433/app-keeps-trying-to-restart-message-service-how-do-i-run-the-message-service-on - Roro

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接