2015-01-08 3 views
0

У меня есть объект JMS, добавленный для запроса объекта, и в методе doPost() метод метода объекта вызывается для получения текущих данных темы, которые будут отправлены клиенту в ответ непрерывно.Несколько запросов сервлета не могут вызвать метод объекта JMS

В другом запросе пользователя одновременно, я не вижу в методе doPost(), получая сообщение, вызываемое или, вернее, получаю пустую/нулевую строку из вызова.

Как заставить метод реагировать на одновременные запросы/пользователей.

Об отладке: во время отладки в затмении иногда я вижу, что оба потока получают данные getMessage.

<jms:listener-container connection-factory="connectionFactory" task-executor="jmsTaskExecutor" destination-type="topic" concurrency="5">  
    <jms:listener destination="abc.topic" ref="abc" method="receive" />  
</jms:listener-container> 

<bean name="jmsTaskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor"> 
    <property name="corePoolSize" value="2"/> 
    <property name="maxPoolSize" value="50"/>  
    <property name="threadNamePrefix" value="some-queue-thread"/> 
</bean> 

<bean id="jmsTopicTemplate" class="org.springframework.jms.core.JmsTemplate"> 
    <property name="connectionFactory" ref="connectionFactory"/> 
    <property name="pubSubDomain" value="true"/> 
</bean> 


@Component("abc") 
public class abc { 

private String msg; 

public synchronized void receive(String msg){  
    this.msg = msg;  
} 


public synchronized String getMessage(){   
    return msg;  
} 
} 

@Component 
@Controller 
public class ForwardController extends ServletForwardingController 
{ 
@Autowired 
abc topicObject; 

@Override 
@RequestMapping("/xyzPath") 
protected ModelAndView handleRequestInternal(HttpServletRequest request, HttpServletResponse response) throws Exception {  
     request.setAttribute("autowired", topicObject); 
     request.getRequestDispatcher("/xyz").forward(request, response); 
    }   
return null; 
} 

@WebServlet("/xyz") 
public class xyz extends HttpServlet { 
protected void doPost(HttpServletRequest request, HttpServletResponse response) { 

abc topicObject = request.getAttribute("autowired"); 

while(true){   
    System.out.println("start"+Thread.currentThread.getId()); 
    String msg = topicObject.getMessage(); 
    response.getWriter.write(msg); 
    System.out.println("stop"+Thread.currentThread.getId()); 
    } 
} 
} 

Что такое правильный способ вызова topicObject.getMessage() одновременно

+0

Я бы настоятельно предложил (как и в другой теме) пересмотреть эту архитектуру. Вы делитесь одним объектом с состоянием между потоками (элемент 'abc'). Thread X перезаписывает значения из Thread Y, теперь изображение еще больше потоков. –

+0

@ M.Deinum Не могли бы вы рассказать о Thread x, Thread Y перезаписывается. В классе abc я нигде не очищаю String msg, так как он очищается. Если есть перезапись, должны быть некоторые данные, я не очень понимаю это. Кроме того, во время отладки я вижу, что часто данные считываются (getMessage()) двумя запросами. – user3747396

+0

У вас есть один экземпляр ABC, который является общим для всех потоков. Изменения состояния просматриваются всеми потоками. Не уверен, что это то, что вы хотите.Как я уже говорил ранее, вы пишете свою собственную фреймворк, и я настоятельно рекомендую воспользоваться стандартными реализациями там. Ваше решение убьет сервер довольно быстро. Также нет смысла пересылать сервлет, поскольку все может быть сделано с контроллера, вы просто добавляете ненужную сложность. –

ответ

0

Удалить аннотацию @Async. Я не уверен, что вы намеревались сделать, но это не так.

От Javadoc:

Однако тип возврата ограничен либо void или Future.

А из Spring framework documentation:

@Async аннотации могут быть предоставлены по методу так, что вызов этого метода будет происходить асинхронно. Другими словами, вызывающий абонент будет немедленно возвращаться после вызова и фактического выполнения , метод будет выполняться в задаче, которая была отправлена ​​в Spring TaskExecutor.

Другими словами, с @Async код не выполняется немедленно, но позже в другом потоке, но он немедленно возвращается. Таким образом, для вашего getMessage вы предоставили тип возвращаемого значения, который не поддерживается, и приводит к неопределенному поведению (случайный, даже в вашем случае).

Для метода receive это также не то, что вы хотите, потому что оно перенесет назначение на message.

Решение: Удалите оба аннотаций @Async и сделать оба метода synchronized так, что вы правильно опубликовать изменения в message переменной, которая делает его видимым во всех потоках.

+0

У меня раньше была попытка синхронизации. но это определенно вызывало только один поток, чтобы видеть данные. Поэтому я сделал это Async. так что по крайней мере иногда другой поток сможет читать данные. – user3747396

+0

Удалите @Async, вы используете его неправильно. И добавьте 'synchronized'. Я не знаю, что такое «Синхронизация», но не добавляйте много аннотаций. 'synchronized' является * правильным способом обработки многопоточной публикации данных на Java. Это позволит всем потокам иметь последовательное представление о вашем 'message' –

+0

. Я сделал изменение кода как предполагаемое, и проблема остается прежней. Пожалуйста, дайте мне знать, если у вас есть идея. – user3747396

Смежные вопросы