【问题标题】:Infinite loop of a service class is preventing creation bean of other service class服务类的无限循环正在阻止其他服务类的创建 bean
【发布时间】:2023-03-28 09:58:01
【问题描述】:

我有 3 个服务类(现在,假设 A、B、C)。它们中的每一个实际上都是一个线程。在我的要求中,他们每个人都应该有一个无限循环。但是每当我运行一个服务类时,其他服务类的无限循环 bean 都不会创建。

如果没有无限循环,则创建每个类的 bean。为什么会这样?

假设它是服务 A。

@Service
@Log4j2
public class A implements Runnable {

    private boolean isRunning = true;

    @Override
    @PostConstruct
    public void run() {
        log.debug("A Thread Started!");

        while (isRunning) {

                // just a sleep for 2 sec
        }
    }
}

假设它是服务 B。

@Service
@Log4j2
public class B implements Runnable {

    private boolean isRunning = true;

    @Override
    @PostConstruct
    public void run() {
        log.debug("B Thread Started!");

        while (isRunning) {

                // just a sleep for 2 sec
        }
    }
}

假设它是服务 C。

@Service
@Log4j2
public class C implements Runnable {

    private boolean isRunning = true;

    @Override
    @PostConstruct
    public void run() {
        log.debug("C Thread Started!");

        while (isRunning) {

                // just a sleep for 2 sec
        }
    }
}

这是我的主要课程:

@SpringBootApplication
@Log4j2
public class Main {

    @Autowired
    public ApplicationContext context;

    public static void main(String[] args) {
        SpringApplication.run(Main.class, args);
    }

    @Bean
    @PostConstruct
    public void createConnection() {

        log.debug("Connecting to Server...");
        // doing some staff
    }
}

现在如果我这样运行,总是得到这个日志:

2020-07-14 21:21:52:129 [main] DEBUG support.DefaultListableBeanFactory:217 - Creating shared instance of singleton bean 'a'
2020-07-14 21:21:52:130 [main] DEBUG service.ProcessorService:27 - A Thread Started!

如果我将任何日志放入 A 类的 while 循环中,那么只会显示那些日志。

如果我对 A 类的循环部分进行评论并保持该类如下:

@Service
@Log4j2
public class A implements Runnable {

    private boolean isRunning = true;

    @Override
    @PostConstruct
    public void run() {
        log.debug("A Thread Started!");

       /* while (isRunning) {

                // just a sleep for 2 sec
        }*/
    }
}

然后在日志中得到这个:

2020-07-14 21:30:31:198 [main] DEBUG support.DefaultListableBeanFactory:217 - Creating shared instance of singleton bean 'a'
2020-07-14 21:30:31:199 [main] DEBUG service.ProcessorService:27 - A Thread Started!
2020-07-14 21:30:31:199 [main] DEBUG support.DefaultListableBeanFactory:217 - Creating shared instance of singleton bean 'b'
2020-07-14 21:30:31:199 [main] DEBUG service.ReceivingProcessingService:46 - B Thread Started!

如果我也评论 B 类的循环部分,那么只会让每个服务类运行。无法理解原因。任何帮助将不胜感激。

【问题讨论】:

标签: java spring-boot


【解决方案1】:

在您的情况下,PostConstruct 方法永远不会结束,因此 spring 无法继续进行。理想情况下,您应该创建一个单独的 MyRunnable 类,它实现 Runnable 并用您的逻辑覆盖其运行方法,并在 post 构造方法中启动一个新线程,如下所示:

@PostConstruct
public void init() {
  log.debug("Starting thread!");
  Thread myThread = new Thread(new MyRunnable());
  myThread.start();
}

您现在可以从服务类中删除“implements Runnable”

【讨论】:

  • 但是,如果我在服务类中自动装配任何引用,那么 spring 将不会创建该 bean。正确的?像这样,spring boot 没有运行线程。我自己做。
  • 运行线程的代码将由 Spring boot 执行,就像在 PostContruct 方法中一样。当您的应用程序启动时,它将调用 init() 方法,该方法将依次启动线程。
  • 那么通过这个 init() 我将如何运行 3 个不同的线程?你想说我可以在 MyRunnable1、MyRunnale2 和 MyRunnable3 类中编写我的逻辑吗?并会删除服务类?
  • 对,如果逻辑不同则创建 3 个可运行对象,或者如果逻辑相同,您可以使用相同的可运行对象,并且在每个服务中使用您选择的可运行对象在 PostConstruct init() 方法中启动一个新线程。不要删除服务类,您仍然需要它们来调用您的 PostConstruct 方法,只是现在不要在这些服务中实现 Runnable 接口。
【解决方案2】:

这就是我更改代码的方式。我现在用的是 ThreadPoolExecutor。

@Configuration
@Log4j2
public class AppConfiguration {
    @Bean
    public ThreadPoolTaskExecutor taskExecutor() {
        log.debug("Config called of taskExecutor...");
        ThreadPoolTaskExecutor pool = new ThreadPoolTaskExecutor();
        pool.setCorePoolSize(3);
        pool.setMaxPoolSize(3);
        pool.setWaitForTasksToCompleteOnShutdown(true);
        pool.initialize();
        return pool;
    }
}

然后像这样运行服务:

private void runServices() {
    ThreadPoolTaskExecutor executor = (ThreadPoolTaskExecutor) context.getBean("taskExecutor");

    A a = context.getBean(A.class);
    executor.execute(a);

    B b = context.getBean(B.class);
    executor.execute(b);

    C c = context.getBean(C.class);
    executor.execute(c);

    log.debug("Active Executor: " + executor.getActiveCount());
}

而且服务类是一样的,只是去掉了PostConstruct注解。

它是服务 A。

@Service
@Log4j2
public class A implements Runnable {

    private boolean isRunning = true;

    @Override
    public void run() {
        log.debug("A Thread Started!");

        while (isRunning) {

                // just a sleep for 2 sec
        }
    }
}

它是服务 B。

@Service
@Log4j2
public class B implements Runnable {

    private boolean isRunning = true;

    @Override
    public void run() {
        log.debug("B Thread Started!");

        while (isRunning) {

                // just a sleep for 2 sec
        }
    }
}

它是服务 C。

@Service
@Log4j2
public class C implements Runnable {

    private boolean isRunning = true;

    @Override
    public void run() {
        log.debug("C Thread Started!");

        while (isRunning) {

                // just a sleep for 2 sec
        }
    }
}

现在一切正常。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-06-08
    • 2013-07-09
    • 1970-01-01
    • 1970-01-01
    • 2014-10-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多