gpt4 book ai didi

java - 带有 ServletContextListener 的线程池

转载 作者:太空宇宙 更新时间:2023-11-04 08:02:29 25 4
gpt4 key购买 nike

我想运行一些简单的后台进程计算,但我似乎无法弄清楚。无论我做什么,它都会阻塞。

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 是因为我不想让它阻塞,所以我将它设为 Runnable 类型,当调用 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());
}
}
}

虽然这应该在它自己的线程上运行,但Hello World!按预期显示多次,但不允许网络应用程序上线。

最佳答案

查看您的源代码,我没有看到实际创建的任何线程。通常,您会执行以下操作来 fork 线程:

new Thread(new WorkThread(...)).start();

这将在新线程中调用 WorkThread.run() 方法。如果您使用 ExecutorService(通常推荐使用 Thread 的“手动”代码),那么您会这样做:

executorService.submit(new WorkThread(...));
...
// when done with the service you have to shut it down
executorService.shutdown();

如果您将 WorkManager 类注入(inject)到监听器类中,那么我只需在管理器上添加一个 submit(...) 方法,并在监听器中执行以下操作:

workManager.submit(new WorkThread());

这意味着 WorkThreadManagerStartUp 类不是必需的。您将工作线程或工作单元提交给服务。

就 Spring 而言,我只需让您的 WorkManager 类实现 InitializingBeanDisposableBean,以便它可以自行启动和停止其服务。没有理由让另一个 bean 这样做。然后,您可以使用管理器管理的 ExecutorService 将管理器注入(inject)到任何想要运行 WorkThread 的类中。

关于java - 带有 ServletContextListener 的线程池,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12632996/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com