Java 何时使用线程池而不是调用新线程
我有一个JAX-RS/Jersey Rest API,它收到一个请求,需要在一个单独的线程中执行额外的工作,但我不确定是否建议使用线程池。我期望有很多对这个API的请求(每天几千个),但我只有一个额外的后台工作 像这样每次只创建一个新线程会不好吗?如有任何建议,将不胜感激。我以前从未使用过线程池Java 何时使用线程池而不是调用新线程,java,multithreading,Java,Multithreading,我有一个JAX-RS/Jersey Rest API,它收到一个请求,需要在一个单独的线程中执行额外的工作,但我不确定是否建议使用线程池。我期望有很多对这个API的请求(每天几千个),但我只有一个额外的后台工作 像这样每次只创建一个新线程会不好吗?如有任何建议,将不胜感激。我以前从未使用过线程池 @Get @Path("/myAPI") public Response myCall() { // call load in the background load(); ... //
@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:
这就是我现在想到的。有谁能告诉我这看起来是否正常(它在本地工作)以及我是否需要关闭执行器(请参阅代码中的注释)
Threadpool是一种很好的处理方法,原因有两个: 1) 您将重用池中的现有线程,这会降低开销 2) 更重要的是,如果系统受到攻击,并且由于池的大小是预先设置的,所以有人试图立即启动数以百万计的会话,您的系统将不会陷入困境
线程池的使用一点也不复杂。请参阅有关线程池的更多信息。再看一看 我建议不要使用您提到的任何一种方法,而是使用JMS队列。您可以轻松地在应用程序中嵌入ActiveMQ实例。首先在后台创建一个或多个单独的使用者线程,以从队列中拾取作业 然后,当收到请求时,只需在JMS队列上推送一条包含作业详细信息的消息。这是一个比摆弄低级线程或线程池更好的体系结构和更具可伸缩性
另请参见:和。我觉得您根本不需要创建多个线程。 (虽然我可能错了,但我不知道你任务的具体细节) 您是否可以创建一个执行后台工作的线程,并为该线程提供一个
LinkedBlockingQueue
,以存储doSomethingBackground
调用的参数
如果立即启动后台任务至关重要,即使服务器负载很重,此解决方案也无法工作。但例如,对于我最近的任务(从外部检索文本,将它们返回给API调用方,然后延迟将文本添加到SOLR层),这是一个非常好的解决方案。我建议您使用线程池,而不是创建新线程。如果您有1000个并发请求,该怎么办?创建1000个线程不是一个好主意。这将消耗您的服务器资源,并影响您的服务响应。您可以在中开始回答。谢谢。我正在考虑使用Executors,但我不确定哪种类型的池适合(单个、缓存、固定等),以及如何确定线程池的大小?很抱歉提出这些基本问题,但正如前面所说的,我以前没有这样做过。@Diyarbakir,正如gioraschc所建议的,这完全取决于你的需要。因此,您必须从某个地方开始,随机应变,并在将来改进您的实现。这就是测试的目的。=]这不是个好主意。让我们假设一个请求处理需要1秒。因此,对X个请求进行排队处理最快需要X秒。如果您的服务器加载了大量请求。。。好。。。作为用户,我将停止使用它;)不,实际上回答用户的线程会立即得到回复。该线程只调用
LinkedBlockingQueue.offer()
。
// 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();
}