Jersey
application Tomcat
server MySQL
database using Hibernate
Netbeans
I'm creating a ScheduledExecutorService
to run everyday at a particular time. However, when it runs it creates many connections to the database. I imagine it's because the threads aren't being destroyed when I rerun the application, so many ScheduledExecutorService
s build up in the JVM and all execute at the same time. But, I'm not sure what the cause is.
I create the ScheduledExecutorService
with a ThreadFactory
that only creates daemon threads, so when I rerun the application I imagine that all daemon threads should be destroyed so that only one ScheduledExecutorService
ever exists.
Here is the creation of the ScheduledExecutorService
:
ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = Executors.defaultThreadFactory().newThread(r);
t.setDaemon(true);
return t;
}
});
Here is how it runs everyday at a particular time:
public void startExecutionAt(int targetHour, int targetMin, int targetSec){
long delay = computeNextDelay(targetHour, targetMin, targetSec);
mExecutorService.schedule(new Runnable() {
@Override
public void run() {
Thread t = new Thread(new CustomRunnable());
t.setDaemon(false);
t.start();
startExecutionAt(targetHour, targetMin, targetSec);
}
}, delay, TimeUnit.SECONDS);
}
I know it's creating many connections to MySQL
because in the P6Spy
log there are many many connections and queries made when CustomRunnable
is executed when CustomRunnable
only runs one Hibernate
query that selects 5 records from a table.
Any ideas as to what could be going on?
You obviously misuse your ScheduledExecutorService
, here is what you are supposed to do:
public void startExecutionAt(int targetHour, int targetMin, int targetSec){
long delay = computeNextDelay(targetHour, targetMin, targetSec);
mExecutorService.scheduleAtFixedRate(
new CustomRunnable(),
1000L * delay,
TimeUnit.DAYS.toMillis(1),
TimeUnit.MILLISECONDS
);
}
You call this method once for all and it will launch your task with delay
as initial delay then every day at the same exact time.
More details here .
Indeed you currently create a new thread any time the task is executed then call again the method to schedule the next execution which is not what you are supposed to do, the task is already executed in a pool no need to create a new Thread
moreover no need to schedule again manually when you can do it directly with the ScheduledExecutorService
.
Response Update:
As the scheduling seems to be more complicated in your case, here is how you should do it instead:
public void startExecutionAt(int targetHour, int targetMin, int targetSec){
long delay = computeNextDelay(targetHour, targetMin, targetSec);
mExecutorService.schedule(new Runnable() {
@Override
public void run() {
try {
new CustomRunnable().run();
} finally {
startExecutionAt(targetHour, targetMin, targetSec);
}
}
}, delay, TimeUnit.SECONDS);
}
This way you won't create and start new threads for nothing.
The second part of your problem should be fixed by starting and shutting down properly your ScheduledExecutorService
respectively on ServletContext
initialized and destroyed, in other words the class that manages your scheduler should be a ServletContextListener
.
public class MyServletContextListener implements ServletContextListener {
private ScheduledExecutorService executorService;
public void contextInitialized(ServletContextEvent sce) {
executorService = Executors.newSingleThreadScheduledExecutor(new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = Executors.defaultThreadFactory().newThread(r);
t.setDaemon(true);
return t;
}
});
}
public void contextDestroyed(ServletContextEvent sce) {
executorService.shutdownNow();
}
public void startExecutionAt(int targetHour, int targetMin, int targetSec){
// code defined above here
}
}
If you need services to make it work, use CDI to get them by injection.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.