使用spring从服务层启动新线程的正确方法

时间:2017-10-23 11:32:06

标签: java spring multithreading service

我有一个很少被调用的方法。此方法在db中收集垃圾。我不想让用户等待服务器响应,所以我决定从我的服务层的新线程调用此方法。我正在使用Spring。 服务类:

@Service
@Transactional
public class UploadService {

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

我不想等待的方法

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

这样做的好方法吗?

2 个答案:

答案 0 :(得分:6)

如果你的类路径上有Spring,你也可以使用@Async

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

在您的主要课程中,您需要使用@EnableAsync,例如:

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

你需要一个执行者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;
}

答案 1 :(得分:1)

我认为提供的解决方案可能会导致您的服务器上出现大量线程。作为替代方案,您可以考虑以这样的方式使用Executors.newSingleThreadExecutor,您将获得仅限于一个线程的执行器服务 - 因此您永远不会创建多个线程 - 这就是您所需要的。另外,当您使用spring时,请考虑将SingleThreadExecutor实例化配置为单独的bean - 这样您将来可以更改ExecutorService的impl。