是否可以使用Spring Boot运行长任务?

时间:2018-08-30 20:43:56

标签: spring multithreading spring-boot threadpoolexecutor

我想使用TaskExecutor在Spring Boot中运行几个长任务。我想让多个rfid阅读器运行并连续获取项目标签。然后,我需要使用这些标签来更新数据库。到目前为止,我无法使用Spring Boot多次运行任务。这可能吗?

我正在创建一个@Component阅读器类。创建时,我启动了侦听器服务,并启动了侦听器以跟踪标签。我有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 个答案:

答案 0 :(得分:4)

Spring Boot没有施加任何限制。如果您可以使用Java或其他语言进行操作,则应该可以使用Java + Spring Boot进行操作。

什么是Spring Boot

需要明确的是,Spring Boot基本上只是一个用于构建Spring项目的框架,该项目历史上非常复杂,并且具有许多样板代码。您可以制作spring boot命令行应用程序或Web应用程序(这是更正常的)。我确信还有更多选择,并且还会来。

因此,Spring Boot通过轻松地从applicaiton.properties文件中公开配置,自动连接所有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:)。
  • 作为命令行工具,此特定应用可能会更好-但如果您需要控制器/ etc来提供任务检查端点或其他功能,则可以将其设为普通的spring boot Web类型。它与您所要询问的任务本身无关紧要。该应用程序一旦完成就不会终止,除非您添加System.exit(),因为它期望它是一个长期存在的Web应用程序。