Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/350.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/394.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 仅当线程池中的线程可用于处理JMS队列中的消息时,才将其从JMS队列中解列_Java_Spring_Spring Jms_Spring Async - Fatal编程技术网

Java 仅当线程池中的线程可用于处理JMS队列中的消息时,才将其从JMS队列中解列

Java 仅当线程池中的线程可用于处理JMS队列中的消息时,才将其从JMS队列中解列,java,spring,spring-jms,spring-async,Java,Spring,Spring Jms,Spring Async,需求是侦听JMS队列,以异步方式处理请求,并在不同的JMS队列上发送响应。系统只允许在一个时刻处理固定数量的请求。除非有线程可用于处理请求,否则不能将其退出队列 使用@JMSListener注释的方法从请求队列中取出请求 递增全局计数器 侦听器通过调用@Async注释的方法来执行请求 如果计数器==线程池的最大大小,则停止侦听。否则,侦听器就可以自由地侦听新请求 Async方法处理该请求,并调用生产者服务中的sendResponse()方法在响应队列上发送响应 生产者方法在响应队列上发送响应,并

需求是侦听JMS队列,以异步方式处理请求,并在不同的JMS队列上发送响应。系统只允许在一个时刻处理固定数量的请求。除非有线程可用于处理请求,否则不能将其退出队列

  • 使用@JMSListener注释的方法从请求队列中取出请求
  • 递增全局计数器
  • 侦听器通过调用@Async注释的方法来执行请求
  • 如果计数器==线程池的最大大小,则停止侦听。否则,侦听器就可以自由地侦听新请求
  • Async方法处理该请求,并调用生产者服务中的sendResponse()方法在响应队列上发送响应
  • 生产者方法在响应队列上发送响应,并递减全局计数器
  • 如果侦听器bean被设置为停止侦听,那么producer方法将设置该bean再次开始侦听
  • 问题是: 由于调用sendResponse()的线程是线程池线程之一,因此在sendResponse()方法完成之前,此线程将不会空闲。这意味着即使计数器已递减,线程仍然不可用

    听众:

    @Service
    public class ActiveMQListener{
    
        @Autowired
        ApplicationContext applicationContext;
    
        @Autowired
        AsyncService aSyncService;
    
        @Autowired
        ThreadPoolCounter threadPoolCounter;
    
        @JmsListener(id = "req1", destination = "RequestQueue1", containerFactory = "jmsFactory")
        public void receiveRequest(ActiveMQTextMessage message) throws JMSException {
            String requestMsg = messget.getText()
            
            //some validation
    
            aSyncService.executeRequest(requestMsg);
    
            if(threadPoolCounter.incrementCounter() == 10){
                JmsListenerEndpointRegistry customRegistry = applicationContext.getBean(JmsListenerEndpointRegistry.class);
                MessageListenerContainer listenerContainer = customRegistry.getListenerContainer("req1");
                listenerContainer.stop();
            }
        }
    }
    
    制作人:

    @Service
    public class ActiveMQProducer {
    
        @Autowired
        JmsTemplate jmsTemplate;
    
        @Autowired
        ThreadPoolCounter threadPoolCounter;
    
        @Autowired
        ApplicationContext applicationContext;
    
    
        public void sendResponse(ActiveMQTextMessage responseMsg) throws JMSException {
            jmsTemplate.convertAndSend("res1" , responseMsg);
    
            threadPoolCounter.decrement();
    
            JmsListenerEndpointRegistry customRegistry = applicationContext.getBean(JmsListenerEndpointRegistry.class);
            MessageListenerContainer listenerContainer = customRegistry.getListenerContainer("req1");
    
            if(!listenerContainer.isRunning()){
                listenerContainer.start();
            }
        }
    }
    
    异步方法:

    @Service
    public class AsyncService{
    
        @Autowired
        ActiveMQProducer activeMQProducer;
    
        @Async("RequestExecutor")
        public void executeRequest(String requestMsg) {
            String resposeMsg = "";
    
            //Some Async Processing
    
            ActiveMQTextMessage message = new ActiveMQTextMessage();
            message.setText(responseMsg);
            activeMQProducer.sendResponse(message);
        }
    
    }
    
    我的想法:
    将侦听器be=的并发性增加到线程池大小。将异步方法的返回类型更改为返回Future。这应该可以解决这样一个问题,即确保只有当线程可以处理请求时,请求才会被出列。但是,在这种情况下,线程的数量增加了一倍。例如,如果线程池大小为10,那么我将有10个侦听器线程等待将来。get()。如果将来必须增加要处理的请求数,那么它可能会受到侦听器线程数的影响

    @Service
    public class ActiveMQListener{
    
        @Autowired
        AsyncService aSyncService;
    
        @Autowired
        ActiveMQProducer activeMQProducer;
    
    
        @JmsListener(id = "req1", destination = "RequestQueue1", containerFactory = "jmsFactory")
        public void receiveRequest(ActiveMQTextMessage message) throws JMSException {
            String requestMsg = messget.getText()
            
            //some validation
    
            Future<String> future = aSyncService.executeRequest(requestMsg);
            String responseMsg = future.get();
    
            activeMQProducer.sendResponse(responseMsg);
        }
    }
    
    @服务
    公共类ActiveMQListener{
    @自动连线
    异步服务异步服务;
    @自动连线
    ActiveMQProducer-ActiveMQProducer;
    @JmsListener(id=“req1”,destination=“RequestQueue1”,containerFactory=“jmsFactory”)
    public void receiveRequest(ActiveMQTextMessage消息)引发JMSException{
    String requestMsg=messget.getText()
    //一些验证
    Future=aSyncService.executeRequest(requestMsg);
    字符串responseMsg=future.get();
    activeMQProducer.sendResponse(responseMsg);
    }
    }
    
    您不是在试图超越框架吗?只需删除
    @Async
    ,并将侦听器设置为多线程。这应该能满足你的需要,而不是像这样把它塞住。我还建议使用
    JmsTemplate
    来发送响应,而不是直接绑定到ActiveMQ.@M.Deinum当我有多个侦听器但应该一次处理10个请求时如何。如果我在两个侦听器(每个侦听器5个)之间拆分并发,并且其中一个侦听器上没有请求,那么我一次只能处理5个请求。您可以使用包含10个线程的
    ThreadPoolTaskExecutor
    配置
    DefaultJMSlinerContainerFactory
    。然后,这些线程将在不同的
    DefaultJmsListenerContainer
    实例之间共享。我强烈建议阅读文档(参考和java文档),其中解释了所有这些。