Reputation: 439
I want to run some simple background process calculations but I can't seem to figure it out. No matter what I do, it blocks.
public class WorkThreadManagerContextLoaderListener implements ServletContextListener {
private Runnable runnable;
private WorkManager workManager;
@Override
public void contextInitialized(ServletContextEvent event) {
final WebApplicationContext springContext = WebApplicationContextUtils.getWebApplicationContext(event.getServletContext());
workManager = (WorkManager) springContext.getBean("workThreadManager");
runnable = new WorkThreadManagerStartUp(WorkManager);
runnable.run();
}
@Override
public void contextDestroyed(ServletContextEvent event) {
workManager.shutDown();
}
}
The reason why WorkThreadManagerStartUp exist is because I don't want it to block so I made it a Runnable type and when run() is called, it starts up an ExecutorService:
public class UnitOfWorkThreadManagerStartUp implements Runnable {
private WorkManager workManager;
public UnitOfWorkThreadManagerStartUp(WorkManager workManager) {
this.workManager = workManager;
}
@Override
public void run() {
workManager.startUp();
}
}
public class WorkThreadManager implements WorkManager {
@Autowired
private WorkService workService;
private final int availableProcessors = Runtime.getRuntime().availableProcessors();
private final ExecutorService executorService = Executors.newFixedThreadPool(4 * availableProcessors);
@Override
public void startUp() {
// this method always blocks...
}
}
But my solution doesn't work as expected. I'm running on Tomcat 7.0.30.
What I'm trying to figure out is how I can start a thread pool in the background without stopping the web app from deploying because currently it can never fully come online due to startUp() always blocking. I'd like to simplify this solution and possibly removing WorkThreadManagerStartUp class if it's not really needed.
EDIT:
I modified the start up class
public class WorkThreadManagerStartUp implements Runnable {
private WorkManager workManager;
public WorkThreadManagerStartUp(WorkManager workManager) {
this.workManager = workManager;
}
@Override
public void run() {
try {
while (true) {
System.out.println("Hello World!");
Thread.sleep(1000 * 10);
}
} catch(InterruptedException e) {
System.out.println(e.getMessage());
}
}
}
Although this is suppose to run on it's own thread, Hello World! displays multiple times as expected but does not allow the web app to come online.
Upvotes: 1
Views: 1977
Reputation: 116888
Looking at your source, I don't see any threads actually being created. Typically you do something like the following to fork a thread:
new Thread(new WorkThread(...)).start();
This will call the WorkThread.run()
method in the new thread. If you are using an ExecutorService
(usually recommended over "by hand" code that uses Thread
) then you would do:
executorService.submit(new WorkThread(...));
...
// when done with the service you have to shut it down
executorService.shutdown();
If you are injecting your WorkManager
class into your listener class then I would just add a submit(...)
method on the manager and in the listener do something like:
workManager.submit(new WorkThread());
This would mean that the WorkThreadManagerStartUp
class is just not necessary. You submit your worker thread or unit of work to the service.
In terms of Spring, I'd just make your WorkManager
class implement InitializingBean
and DisposableBean
so it can start and stop its service itself. No reason to have another bean do that. Then you can inject the manager into any class that wants to run a WorkThread
using the ExecutorService
managed by the manager.
Upvotes: 1