2015-01-08 2 views
0

요청 객체에 JMS 객체가 추가되고 doPost() 메소드에서 객체의 get 메소드가 호출되어 응답으로 클라이언트에 전송 될 현재 항목 데이터를 가져옵니다. 연방.다중 서블릿 요청이 JMS 객체의 메소드를 호출 할 수 없음

동시에 다른 사용자가 요청할 경우 doPost() 메서드에서 get 메시지가 호출되거나 호출에서 빈/null 문자열을 수신하는 것을 볼 수 없습니다.

동시 요청/사용자에 대해 응답 방식을 유지하는 방법.

디버깅 : Eclipse에서 디버깅하는 동안 두 스레드가 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 String을 지우지 않습니다. 그래서 어떻게 지워지 죠. 여전히 덮어 쓰기가 있다면, 약간의 데이터가 있어야합니다. 이것에 대해서는별로 명확하지 않습니다. 또한 디버깅하는 동안 두 개의 요청에 의해 데이터가 읽히는 경우가 종종 있습니다 (getMessage()). – user3747396

+0

모든 스레드간에 공유되는 ABC의 단일 인스턴스가 있습니다. 상태 변경은 모든 스레드에서 볼 수 있습니다. 그것이 당신이 원하는 것인지 확실하지 않습니다.앞에서 이미 언급했듯이 자신 만의 프레임 워크를 작성하고 있으므로 표준 구현을 통해 알 수 있습니다. 당신의 솔루션은 서버를 아주 빨리 죽일 것입니다. 또한 컨트롤러에서 모든 것을 수행 할 수 있으므로 서블릿으로 전달하는 것은 의미가 없으며 불필요한 복잡성을 추가하는 것입니다. –

답변

0

@Async 주석을 제거 호출 할 수있는 권리 방법은 무엇입니까. 나는 네가 의도 한 바를 잘 모르지만 그렇게하지는 않는다. Javadoc에서

:

그러나, 반환 형식은 void 또는 Future 하나에 제한됩니다.

그리고 Spring framework documentation에서

:

@Async 주석

비동기 발생 메소드의 호출 있도록하는 방법을 제공 할 수있다. 즉, 호출자 이 호출 즉시 반환되고 의 실제 실행은 Spring TaskExecutor에 제출 된 태스크에서 발생합니다.

즉, @Async를 사용하면 코드가 즉시 실행되지 않고 나중에 다른 스레드에서 실행되지만 즉시 반환됩니다. 따라서 getMessage의 경우 지원되지 않는 반환 유형을 제공하고 정의되지 않은 동작 (귀하의 경우에는 임의의 경우에도)이 발생합니다.

메서드의 경우 할당 방법을 message으로 지정하기 때문에 원하는 방식이 아닙니다.

솔루션 : 모두 @Async 주석을 제거하고 올바르게 모든 스레드에는 표시하게 message 변수에 변경 사항을 게시 너무 두 가지 방법 synchronized을합니다.

+0

나는 이전에 동기화를 시도했습니다. 그러나 단 하나의 스레드가 데이터를 볼 수있게하는 것은 분명했습니다. 나는 비동기로 만들었다. 최소한 다른 스레드가 데이터를 읽을 수 있어야합니다. – user3747396

+0

@Async를 제거하십시오. 잘못 사용하고 있습니다. 그리고'synchronized'를 추가하십시오. 나는'Sync'가 무엇인지 모르지만 많은 주석을 추가하지는 않습니다. 'synchronized '는 Java에서 다중 스레드 데이터 게시를 처리하는 * 적절한 방법입니다. 모든 쓰레드가 당신의'message'에서 일관된 뷰를 가질 수 있습니다. –

+0

나는 코드 변경을했고 여전히 문제는 동일하게 남아 있습니다. 아이디어가 있으면 알려주세요. – user3747396