问题
Having read a lot of different things and not being totally familiar with the correct terms for some of these things, I am wondering what the correct way is for creating threads at time of tomcat startup that have a specific purpose. I am using a linux system.
I am not trying to create a thread from a servlet, and I have a good idea of why this is bad. When tomcat starts up, I want two different threads that have a distinct purpose to start. The first thread runs on a period, every 30 minutes, to audit back-end data. The second thread is responsible for sending emails. When a request runs a servlet where an email must be sent, instead of holding up the servlet waiting for the email to be sent, I want to send a request to this email thread and move on. So one runs periodically, and one runs on demand. I never need to increase the number of threads performing these tasks, I just need these two going, and for it to be going as long as the webapp is running, and if the webapp has to halt, I don't really care about graceful shutdown.
There are a few approaches I know that I could take:
Create a process running outside of tomcat and define a way to communicate with that process from my servlet. I'd like to avoid this if possible, because I'd like for these two threads to first be directly associated with start up and shut down of the webapp, and for them to be able to access data in the
ServletContext
, and to not have to ser/des data across a communication channel.Spawn two threads in the
init
method of one of my servlets. This seems dirty and hackish, but it would definitely get the job done.Create a
ServletContextListener
that extends aThreadPoolExecutor
or otherExexutorService
. This seems appealing and correct, and I suppose I could do a fixed thread pool of 2 threads because I don't need any more. But is this the recommended way to do what I am trying? I understand that anExecutorService
is really more meant for executingRunnable
s on the fly without having to lose the overhead of creating a thread. I don't know if that is totally right, but if it is, I would not be using an executor for its meant purpose.
Maybe there are more methods that I do not know about, or a correct way to implement one of the above.
回答1:
Please refer to the following Q&A: tomcat 6 thread pool for asynchronous processing.
Also, instead of Executors.newFixedThreadPool
you'll probably need Executors.newScheduledThreadPool
to create instance of ScheduledExecutorService
which is capable of executing repeating tasks.
Hope this helps...
回答2:
i will not go on implementing the Thread pool itself, but on your question:
Correct way to create task threads in tomcat at startup
as others said, your third approach is almost correct BUT this depends on your Service Structure.
i'll give you an example and then explain it:
public class YourServletContextListener implements ServletContextListener{
@Override
public void contextDestroyed(ServletContextEvent sce) {
}
@Override
public void contextInitialized(ServletContextEvent sce) {
}
}
From the Docs:
contextInitialized:
All ServletContextListeners are notified of context initialization before any filter or servlet in the web application is initialized.
if i understand your approach correctly, then i would ask you: how would you like to start a service or send any request to a servlet that is still not been initialized?
this would work, if Services you would like to start do not communicate/need any servlet or Filter or any Data from the web App directly. later, after startup the container, they can sure communicate with each other.
as i said before, which way is the best to use depends on the Service Structure/Logic.
One other method may be using a filter:
void init(FilterConfig filterConfig) throws ServletException
Called by the web container to indicate to a filter that it is being placed into service. The servlet container calls the init method exactly once after instantiating the filter.
void destroy()
Called by the web container to indicate to a filter that it is being taken out of service. This method is only called once all threads within the filter's doFilter method have exited or after a timeout period has passed. After the web container calls this method, it will not call the doFilter method again on this instance of the filter.
This method gives the filter an opportunity to clean up any resources that are being held (for example, memory, file handles, threads) and make sure that any persistent state is synchronized with the filter's current state in memory.
but a filter is not designed for such approachs!
Use a Filter if you want to intercept on HTTP requests maching a specific URL pattern because you want to check/modify the HTTP request/response. Use a ServletContextListener if you want to intercept on webapp's startup and/or shutdown.
来源:https://stackoverflow.com/questions/26101321/correct-way-to-create-task-threads-in-tomcat-at-startup