Java 具有ServletContextListener的线程池
我想运行一些简单的后台进程计算,但我似乎无法理解。不管我做什么,它都会阻塞Java 具有ServletContextListener的线程池,java,multithreading,Java,Multithreading,我想运行一些简单的后台进程计算,但我似乎无法理解。不管我做什么,它都会阻塞 public class WorkThreadManagerContextLoaderListener implements ServletContextListener { private Runnable runnable; private WorkManager workManager; @Override public void contextInitialized(Servle
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();
}
}
WorkThreadManagerStartUp之所以存在,是因为我不想阻止它,所以我将其设置为可运行类型,并且在调用run()时,它会启动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...
}
}
但我的解决方案并没有如预期的那样有效。我正在运行Tomcat 7.0.30
我想弄明白的是,我如何在后台启动线程池,而不停止部署web应用,因为由于startUp()始终处于阻塞状态,目前它无法完全联机。我想简化这个解决方案,如果不需要WorkThreadManagerStartUp类,还可以删除它
编辑:
我修改了启动课程
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());
}
}
}
虽然这是假设运行在它自己的线程,你好世界!按预期显示多次,但不允许web应用联机。查看您的源代码,我没有看到任何实际创建的线程。通常,您可以执行以下操作来分叉线程:
new Thread(new WorkThread(...)).start();
这将在新线程中调用WorkThread.run()
方法。如果您使用的是执行器服务
(通常推荐使用线程的“手动”代码),则您可以执行以下操作:
executorService.submit(new WorkThread(...));
...
// when done with the service you have to shut it down
executorService.shutdown();
如果将WorkManager
类注入到侦听器类中,那么我只需在管理器上添加一个submit(…)
方法,并在侦听器中执行如下操作:
workManager.submit(new WorkThread());
这意味着不需要使用WorkThreadManagerStartUp
类。您向服务提交工作线程或工作单元
就Spring而言,我只需要让您的WorkManager
类实现InitializingBean
和DisposableBean
,这样它就可以自己启动和停止服务了。没有理由让另一个豆子这么做。然后,您可以使用管理器管理的ExecutorService
将管理器注入任何想要运行工作线程的类。查看您的源代码,我没有看到任何实际创建的线程。通常,您可以执行以下操作来分叉线程:
new Thread(new WorkThread(...)).start();
这将在新线程中调用WorkThread.run()
方法。如果您使用的是执行器服务
(通常推荐使用线程的“手动”代码),则您可以执行以下操作:
executorService.submit(new WorkThread(...));
...
// when done with the service you have to shut it down
executorService.shutdown();
如果将WorkManager
类注入到侦听器类中,那么我只需在管理器上添加一个submit(…)
方法,并在侦听器中执行如下操作:
workManager.submit(new WorkThread());
这意味着不需要使用WorkThreadManagerStartUp
类。您向服务提交工作线程或工作单元
就Spring而言,我只需要让您的WorkManager
类实现InitializingBean
和DisposableBean
,这样它就可以自己启动和停止服务了。没有理由让另一个豆子这么做。然后,您可以使用管理器管理的ExecutorService
将管理器注入任何想要运行WorkThread
的类。通常,您将需要完成的工作放在Runnable的run方法中,让线程隐式调用该方法,但您自己正在调用它。不太清楚你想做什么。您所说的方法中有什么是阻塞的?我正在从ServletContextListener实例化WorkThreadManagerStartUp。当我调用run方法时,我希望它在后台继续工作,而不会中断web应用程序的启动代码>,您应该执行新线程(runnable).start()代码>。这样它将在一个新的独立线程中运行。没有错误。是的。我应该叫start而不是run。我现在明白你所说的“自己调用它”是什么意思了。通常你把需要做的事情放在Runnable的run方法中,让线程隐式地调用该方法,但你自己调用它。不太清楚你想做什么。您所说的方法中有什么是阻塞的?我正在从ServletContextListener实例化WorkThreadManagerStartUp。当我调用run方法时,我希望它在后台继续工作,而不会中断web应用程序的启动代码>,您应该执行新线程(runnable).start()代码>。这样它将在一个新的独立线程中运行。没有错误。是的。我应该叫start而不是run。我现在明白你所说的“自己调用它”是什么意思了。我同意你应该将executor服务作为一种通用的良好实践。您可能还需要一种方法来监视您提交的可运行/可调用任务,并可能让它使用future返回结果。顺便说一句,我没有使用web服务器的经验,但是在web服务器中管理自己的线程不是很糟糕吗?难道没有办法让服务器为您这样做吗?我同意您应该将executor服务作为一种通用的良好实践。您可能还需要一种方法来监视您提交的可运行/可调用任务,并可能让它使用future返回结果。顺便说一句,我没有使用web服务器的经验,但是在web服务器中管理自己的线程不是很糟糕吗?难道没有办法让服务器为您做这件事吗?