【问题标题】:Is it possible to run a long task using Spring Boot?是否可以使用 Spring Boot 运行长时间的任务?
【发布时间】:2018-08-30 20:43:55
【问题描述】:

我想通过 Spring Boot 使用 TaskExecutor 运行几个长任务。我想让多个 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;
}

【问题讨论】:

  • 一切皆有可能。显示代码,我们将提供帮助。

标签: spring multithreading spring-boot threadpoolexecutor


【解决方案1】:

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(); }
    }
}

更多信息

  • 如果您需要最终获得结果并等待结果,您可以安排 callables 而不是 runnables。
  • 如果除了长时间运行的任务之外还需要计划任务,执行器服务有很多变体。
  • 您可以使用任意数量的线程;只需增加 10 :)。
  • 这个特定的应用程序作为命令行应用程序可能会更好 - 但我将其设置为普通的 Spring Boot Web 类型,以防您需要控制器/等来提供任务检查端点或其他服务。它非常无关紧要,因为您主要是在询问任务本身。除非您添加 System.exit(),否则此应用在完成后不会终止,因为它期望成为一个长期存在的网络应用。

【讨论】:

  • 用 Spring 的 ApplicationRunnerCommandLineRunner bean 替换 Java 的 public static void main 可能会更好(以使其与问题保持一致)
  • 没错,假设他已经有一个正在运行的应用程序,但回想起来这是一个非常好的观点:)。稍后或明天当我靠近 PC 时,我会提供一个。
  • @MaxFarsikov - 有一个完整的例子。
  • 谢谢!这很好用。但是现在当我运行我的代码时,我收到错误,因为它一直在尝试重新启动消息服务。我怎样才能只启动一次消息服务?
  • 这是一个不同的问题,需要您/等提供更多代码。请在此处接受答案并打开一个带有错误和您的任务代码的新问题(尽可能少地重现错误),人们会在那里为您提供帮助。也可以在这里链接它,以便每个人都看到它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-08
  • 1970-01-01
  • 2014-05-07
  • 1970-01-01
  • 1970-01-01
  • 2022-12-01
相关资源
最近更新 更多