Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Proper way to start new thread from service layer using spring

I have a method that will be rarely called. This method collect garbage in db. I don't want to make user to wait for server response so i decided to call this method from new thread from my service layer. i'm using Spring. Service class:

@Service
@Transactional
public class UploadService {

    @Resource(name = "UploadDAO")
    private UploadDao uploadDao;

Method that i don't want to wait for

public void collectBlobGarbage(){
        Thread th = new Thread(new Runnable() {
            @Override
            public void run() {
                uploadDao.collectBlobGarbage();
            }
        });
        th.start();
    }

Is it a good way to do like this?

like image 698
JaneXQ Avatar asked Oct 23 '17 11:10

JaneXQ


People also ask

How do I start a thread in spring boot?

An Executor can be used to start the thread at any point throughout the application's execution. Loading cached data as a Spring application boots up is one example. To accomplish this, the Executor call would be made in the Spring Boot application's main method, prior to the SpringApplication. run().

How do I start a new thread?

Starting a Thread With a Runnable Thread thread = new Thread(runnable); thread. start();

Which method of the thread object can be used to start a new thread?

The start() method of thread class is used to begin the execution of thread.

What does service layer do in spring boot?

A service layer is a layer in an application that facilitates communication between the controller and the persistence layer. Additionally, business logic is stored in the service layer. It includes validation logic in particular. The model state is used to communicate between the controller and service layers.


2 Answers

If you have Spring on your classpath you might as well use @Async

@Async
public CompletableFuture<Void> collectBlobGarbage() throws InterruptedException {
    CompletableFuture.completeFuture(uploadDao.collectBlobGarbage());
}

On your main class you need to use @EnableAsync like:

@SpringBootApplication
@EnableAsync
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

And you need an executor bean:

@Bean
public Executor asyncExecutor() {
    ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
    executor.setCorePoolSize(2);
    executor.setMaxPoolSize(2);
    executor.setQueueCapacity(500);
    executor.setThreadNamePrefix("Stackoverflow-");
    executor.initialize();
    return executor;
}
like image 145
Turbut Alin Avatar answered Oct 20 '22 01:10

Turbut Alin


I think the provided solution can potentially cause a lot of threads on you server.

As an alternative, you can consider using Executors.newSingleThreadExecutor in such a way that you will get an executor service that is limited only to one thread—so you will never create more than one thread—and that is what you need.

Also as you are using Spring, consider configuring a SingleThreadExecutor instantiation as a separate bean—in such a way that you will be able to change the implementation of ExecutorService in the future.

like image 20
Oleksandr Papchenko Avatar answered Oct 20 '22 00:10

Oleksandr Papchenko