简体   繁体   English

使用Executor和WebSocket的多线程

[英]Multithread using Executor and WebSocket

In my case, I want to create multiple thread executor to handle trap received. 就我而言,我想创建多个线程执行程序来处理接收到的陷阱。 In same application, I want to implement websocket to make my application running real time. 在同一应用程序中,我想实现websocket以使我的应用程序实时运行。

I have configuration class to create ThreadPoolExecutor, like this 我有配置类来创建ThreadPoolExecutor,像这样

@Configuration
@EnableAsync
@EnableScheduling
@Profile("!" + Constants.SPRING_PROFILE_FAST)
public class AsyncConfiguration implements AsyncConfigurer, EnvironmentAware {
 .......
 @Override
    @Bean
    public Executor getAsyncExecutor() {
        log.debug("Creating Async Task Executor");
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(propertyResolver.getProperty("corePoolSize", Integer.class, 30));
        executor.setMaxPoolSize(propertyResolver.getProperty("maxPoolSize", Integer.class, 150));
        executor.setQueueCapacity(propertyResolver.getProperty("queueCapacity", Integer.class, 10000));
        executor.setThreadNamePrefix("ems-Executor-");
        return new ExceptionHandlingAsyncTaskExecutor(executor);
    }

Then I use the executor in my TrapReceiver class, 然后在TrapReceiver类中使用执行程序,

@Component
public class TrapReceiver extends Thread implements CommandResponder {

    @Inject
    private ApplicationContext applicationContext;

    @Inject
    private Executor executor;

    public TrapReceiver(){
    }

    List<PDUv1> listPdu = new ArrayList<PDUv1>();
    String message = "";
    long totReceivedTrap = 0;

    @PostConstruct
    public void init() {
        //create thread pool untuk memanage thread puller (thread yang pull dan save device oid value)
        System.out.println("Running trap listener");
        this.start();
    }

    public synchronized void processPdu(CommandResponderEvent cmdRespEvent) {
        PDUv1 pdu = (PDUv1) cmdRespEvent.getPDU();
        listPdu.add(pdu);
        if (pdu != null) {
            if(listPdu.size() == 3){ //3trap per thread
                List<PDUv1> temp = new ArrayList<PDUv1>();
                temp.addAll(listPdu);
                TrapInsertor trapInsertor = (TrapInsertor) applicationContext.getBean("trapInsertor");
                trapInsertor.setProperty(temp);
                executor.execute(trapInsertor);
                listPdu.clear();
            }
        }
        totReceivedTrap++;
        if(totReceivedTrap % 10000 == 0)
            System.out.println("total received trap "+totReceivedTrap);
    }

    public void run() {
        while (true) {
            try {
                this.listen(new UdpAddress(getIp()+"/162")); //where to listen
            } catch (Exception e) {
                e.printStackTrace();
            } 
        }
    }

This code run well, but when I try to add websocket feature in my application, the application got error. 此代码运行良好,但是当我尝试在应用程序中添加websocket功能时,应用程序出现错误。 The error come when I use @EnableWebSocketMessageBroker annotation. 当我使用@EnableWebSocketMessageBroker批注时,将出现错误。 This is my websocket configuration 这是我的websocket配置

@Configuration
@EnableWebSocketMessageBroker
public class WebSocketAppConfig extends AbstractWebSocketMessageBrokerConfigurer {

    @Override
    public void configureMessageBroker(MessageBrokerRegistry config) {
        config.enableSimpleBroker("/topic");
        config.setApplicationDestinationPrefixes("/app");
    }

And this is the error 这是错误

Caused by: org.springframework.beans.factory.BeanCreationException: Could not autowire field: private java.util.concurrent.Executor com.satunol.ems.snmp.TrapReceiver.executor; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [java.util.concurrent.Executor] is defined: expected single matching bean but found 5: getAsyncExecutor,messageBrokerSockJsTaskScheduler,clientInboundChannelExecutor,clientOutboundChannelExecutor,brokerChannelExecutor
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:555)
    at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:87)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:331)
    ... 16 more
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [java.util.concurrent.Executor] is defined: expected single matching bean but found 5: getAsyncExecutor,messageBrokerSockJsTaskScheduler,clientInboundChannelExecutor

What is wrong with my code, if I wrong in websocket configuration or in threadpool, how it should be. 我的代码有什么问题,如果我在websocket配置或线程池中有问题,应该怎么办。

The problem here is since there are multiple possible bean for [java.util.concurrent.Executor], Spring is unable to pick the correct one. 这里的问题是因为[java.util.concurrent.Executor]有多个可能的bean,Spring无法选择正确的bean。 Spring autowire mechanism is based by default on type. Spring自动装配机制默认基于类型。 Since WebSocket has its own ThreadPoolTaskExecutor implementations you ended with 5 possible beans. 由于WebSocket有其自己的ThreadPoolTask​​Executor实现,因此您以5种可能的bean结尾。

The autowire mechanism is based on the assumption that you'll give a single matching bean without any other annotation. 自动装配机制基于以下假设:您将给出一个匹配的Bean,而没有任何其他注释。 Since there are multiple matching beans, you need to tell Spring the one you want to autowire. 由于有多个匹配的bean,因此需要告诉Spring您要自动装配的bean。 You can achieve it with the annotation @Qualifier("beanName") 您可以使用批注@Qualifier(“ beanName”)来实现

@Autowired
@Qualifier("getAsyncExecutor")
private Executor executor;

Hope this help ! 希望对您有所帮助!

Some example: Example of @Qualifier annotation 一些示例: @Qualifier注释的示例

This neither issue with multi-threading not with web-socket, this problem with Spring and its auto wiring feature. 这与多线程无关,与Web套接字无关,与Spring及其自动接线功能无关。 See the error - 看到错误-

Caused by: org.springframework.beans.factory. 造成原因:org.springframework.beans.factory。 BeanCreationException : Could not autowire field : private java.util.concurrent.Executor com.satunol.ems.snmp.TrapReceiver.executor; BeanCreationException无法自动装配字段 :私有java.util.concurrent.Executor com.satunol.ems.snmp.TrapReceiver.executor; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [java.util.concurrent.Executor] is defined: expected single matching bean but found 5: getAsyncExecutor,messageBrokerSockJsTaskScheduler,clientInboundChannelExecutor,clientOutboundChannelExecutor,brokerChannelExecutor 嵌套的异常是org.springframework.beans.factory.NoUniqueBeanDefinitionException: 没有定义类型为 [java.util.concurrent.Executor]的合格bean :期望的单个匹配bean,但是找到了5:getAsyncExecutor,messageBrokerSockJsTaskScheduler,clientInboundChannelExecutor,clientOutboundChannelExecutor,brokerChannelExecutor

My recommendation: Remove threadpool and threadpoolexecutor tags and add spring and spring-annotations tag, and some Spring folk should be able to help you quickly. 我的建议:删除threadpoolthreadpoolexecutor标记,并添加springspring-annotations标记,并且一些Spring人士应该能够迅速为您提供帮助。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM