何时使用线程池而不是调用新线程

时间:2015-07-29 11:44:37

标签: java multithreading

我有一个JAX-RS / Jersey Rest API获取请求,需要在单独的线程中执行额外的工作,但我不确定是否建议使用线程池。我希望这个API有很多请求(每天几千),但我在后台只有一个额外的工作。

每次像这样创建一个新线程会不好?任何意见,将不胜感激。我之前没有使用过ThreadPool。

@Get
@Path("/myAPI")
public Response myCall() {
  // call load in the background
  load();
  ...
  // do main job here
  mainJob();
  ...
}

private void load() {
    new Thread(new Runnable() {
        @Override
        public void run() {
            doSomethingInTheBackground();
        }
    }).start();
}

修改 只是为了澄清。我只需要一个额外的工作就可以在后台运行。这项工作将调用另一个API来记录一些信息,这就是它。但它必须为每个请求执行此操作,我不需要等待响应。这就是为什么我想在新的后台线程中这样做的原因。

EDIT2: 所以这就是我现在提出来的。任何人都可以告诉我,如果这似乎没问题(它在本地工作),如果我需要关闭执行程序(请参阅我在代码中的评论)?

// Configuration class
@Bean (name = "executorService")
public ExecutorService executorService() {
    return Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() + 1);
}

// Some other class
@Qualifier("executorService")
@Autowired
private ExecutorService executorService;
....
private void load() {
    executorService.submit(new Runnable() {
        @Override
        public void run() {
            doSomethingInTheBackground();
        }
    });

    // If I enable this I will get a RejectedExecutionException 
    // for a next request.
    // executorService.shutdown();
}

3 个答案:

答案 0 :(得分:4)

Threadpool是解决这个问题的好方法,原因有两个:

1)您将重用池中的现有线程,减少开销 2)更重要的是,如果系统受到攻击,您的系统将不会陷入困境,并且由于池的大小将被预设,某些方尝试立即启动数以万计的会话。

使用线程池并不复杂。有关线程池的更多信息,请参阅here。还要看看oracle documentation

答案 1 :(得分:1)

我建议不使用您提到的方法,而是使用JMS队列。您可以轻松地在应用程序中嵌入ActiveMQ实例。首先在后台创建一个或多个单独的使用者线程,以从队列中获取作业。

然后,当收到请求时,只需在JMS队列上按下包含作业详细信息的消息。这是一个更好的架构,比摆弄低级线程或线程池更具可扩展性。

另请参阅:this answerthe activeMQ site

答案 2 :(得分:1)

听起来你根本不需要创建多个线程。 (虽然我可能错了,但我不知道你的任务的具体细节。)

您是否可以创建一个完成后台工作的线程,并为该线程提供LinkedBlockingQueue来存储doSomethingInTheBackground调用的参数?

如果后台任务立即启动,即使服务器负载很重,这个解决方案也不会起作用。但是例如对于我最近的任务(从外部检索文本,将它们返回到API调用者,然后将文本延迟添加到SOLR层)这是一个非常好的解决方案。