如何在 Spring 引导应用程序中覆盖线程池

How to override the thread pool in Spring Boot app

我正在编写下面的代码来覆盖线程池。但它不能正常工作。在 spring 启动应用程序启动时设置覆盖线程池的正确方法是什么。请注意,我的代码无法控制 Server 实例,因此实例化服务器不是满足我需要的解决方案。

        @Bean
        public EmbeddedServletContainerCustomizer getContainerCustomizer() {
            return (configurableEmbeddedServletContainer) -> {
                if (configurableEmbeddedServletContainer instanceof JettyEmbeddedServletContainerFactory) {
                    ((JettyEmbeddedServletContainerFactory)configurableEmbeddedServletContainer).addServerCustomizers((server) -> {
                        QueuedThreadPool newPool = new QueuedThreadPool(10);
                        QueuedThreadPool oldPool = server.getBean(QueuedThreadPool.class);
                        server.updateBean(oldPool, newPool);        
                    });
                }
            };
        }

当我执行代码时,它抛出了以下错误 线程异常 "main"

java.util.concurrent.RejectedExecutionException: org.eclipse.jetty.io.ManagedSelector@1ee0005 id=0 keys=0 selected=0
    at org.eclipse.jetty.util.thread.QueuedThreadPool.execute(QueuedThreadPool.java:377)
    at org.eclipse.jetty.io.SelectorManager.execute(SelectorManager.java:125)
    at org.eclipse.jetty.io.SelectorManager.doStart(SelectorManager.java:255)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.start(ContainerLifeCycle.java:132)
    at org.eclipse.jetty.util.component.ContainerLifeCycle.doStart(ContainerLifeCycle.java:106)
    at org.eclipse.jetty.server.AbstractConnector.doStart(AbstractConnector.java:260)
    at org.eclipse.jetty.server.AbstractNetworkConnector.doStart(AbstractNetworkConnector.java:81)
    at org.eclipse.jetty.server.ServerConnector.doStart(ServerConnector.java:244)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)
    at org.eclipse.jetty.server.Server.doStart(Server.java:384)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:68)

我也尝试了示例主代码,它也给出了同样的错误。

public class FileServer
{
    public static void main(String[] args) throws Exception
    {
         Server server = new Server(9090);

        QueuedThreadPool newPool = new QueuedThreadPool(10);
        QueuedThreadPool oldPool = server.getBean(QueuedThreadPool.class);
        server.updateBean(oldPool, newPool);


        ResourceHandler resource_handler = new ResourceHandler();

        resource_handler.setDirectoriesListed(true);
        resource_handler.setWelcomeFiles(new String[]{ "index.html" });
        resource_handler.setResourceBase(".");

         HandlerList handlers = new HandlerList();
        handlers.setHandlers(new Handler[] { resource_handler, new DefaultHandler() });
        server.setHandler(handlers);

         server.start();
        server.join();
    }
}

这里是在 Jetty 中使用属性和不同类型的线程池配置线程池的示例。我的线程池是 InstrumentedQueuedThreadPool.

@Configuration
public class CustomJettyConfiguration {

    @Bean
    public JettyEmbeddedServletContainerFactory jettyEmbeddedServletContainerFactory(
            @Value("${server.port:8080}") final String port,
            @Value("${jetty.threadPool.maxThreads:600}") final String maxThreads,
            @Value("${jetty.threadPool.minThreads:10}") final String minThreads,
            @Value("${jetty.threadPool.idleTimeout:5000}") final String idleTimeout) {
        final JettyEmbeddedServletContainerFactory factory =
                new JettyEmbeddedServletContainerFactory(Integer.valueOf(port));

        // Tweak the connection pool used by Jetty to handle incoming HTTP connections
        InstrumentedQueuedThreadPool instThreadPool =
                new InstrumentedQueuedThreadPool(registry);
        instThreadPool.setPrefix("jetty");
        instThreadPool.setMaxThreads(Integer.valueOf(maxThreads));
        instThreadPool.setMinThreads(Integer.valueOf(minThreads));
        instThreadPool.setIdleTimeout(Integer.valueOf(idleTimeout));
        factory.setThreadPool(instThreadPool);

        ...
        return factory;
    }
}

在 spring 引导 2.x 中,JettyEmbeddedServletContainerFactory 已被 org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory 替换。

需要自定义JettyServletWebServerFactory并设置自己的线程池

@Component
public class JettyConfiguration implements WebServerFactoryCustomizer<JettyServletWebServerFactory> {

    @Override
    public void customize(JettyServletWebServerFactory factory) {
        // customize your thread pool here
        QueuedThreadPool qtp = new QueuedThreadPool(80, 500);
        qtp.setName("jettyThreadPool");
        factory.setThreadPool(qtp);
    }
}