[Spring] <task:executor> @Async 를 이용한 쓰레드 중복 테스트

2014. 1. 24. 14:59OpenSource/Spring MVC

반응형

 

 

 

title : [Spring] <task:executor> @Async 를 이용한 쓰레드 중복 테스트

 

index

1.

2. 시나리오

3.

4. 테스트 코드

5. 참고 사이트

 

<< >>

1) SpringFramework 3.1

2) JUnit TEST

3) Log4j - Log쪽에 쓰레드 관련 녀석이 찍히도록 해놓음.

4) 설 정

   <task:annotation-driven executor="asyncExecutor" />

   <task:executor id="asyncExecutor" pool-size="50" />

 

task:annotation : @Async를 사용 할 수 있겠죠잉~

task:executor :

 

<< 시나리오 >>

1) TEST-A : Thread Pool 50    / 호출 10

2) TEST-B : Thread Pool 50    / 호출 1000

2) TEST-C : Thread Pool 2000 /  호출 1000

 

<< >>

1) TEST-A : 중복 없음.

2) TEST-B : 중복 현상 나타남. Thread Pool 50, 호출은 1000 중복이 나다가 어느 시점에서 상이한 Thread 호출.

3) TEST-C : 중복 없음. Thread Pool 2000, 호출 1000


<< 테스트 코드 >>


1) 테스트 코드 - log4j 관련 녀석을 쓰기 위해서 @RunWith를 사용 함. 그냥 System.out.println으로 테스트 시

    AsyncThread.java에서 logger 대신 System.out.println으로 출력하면 됩니다~^-^good~

package kr.pe.acet.async;

import org.junit.Test;

import org.junit.runner.RunWith;

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.test.context.ContextConfiguration;

import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;


import com.kt.log4kt.KTLogger;

import com.kt.log4kt.KTLoggerFactory;



@RunWith(SpringJUnit4ClassRunner.class)

@ContextConfiguration(locations = {

        "classpath:spring/context/async/context-test-properties.xml",

        "classpath:spring/context/async/context-test-common.xml", 

        "classpath:spring/context/async/context-test-mybatis.xml",

        "classpath:spring/context/async/context-test-datasource.xml",     

        "classpath:spring/context/async/context-test-mail.xml",        

        "classpath:spring/context/async/context-test-servlet.xml"})

        

public class AsyncAnnoTest {

KTLogger logger = KTLoggerFactory.getLogger(AsyncAnnoTest.class);


@Autowired AsyncThread asyncThread;

@Test

public void asyncAnnotationTest() {

//AsyncThread asyncThread = new AsyncThread();  동작하지 않음!! @Autowired를 해야함!

int scope = 1000;

logger.debug4Dev("==============[start]===================");

for(int i=0; i < scope; i++){

//asyncThread.threadAndLogTest2();

asyncThread.threadAndLogTest();

//asyncThread.threadAndLogTest3();

}

//asyncThread.threadAndLogTest2();

logger.debug4Dev("==============[end]===================");

}


}



AsyncThread.java

package kr.pe.acet.async;

import org.springframework.scheduling.annotation.Async;

import org.springframework.stereotype.Component;

import org.springframework.stereotype.Service;


import com.kt.log4kt.KTLogger;

import com.kt.log4kt.KTLoggerFactory;


@Component

public class AsyncThread {

private KTLogger logger = KTLoggerFactory.getLogger(AsyncThread.class);

private static int cnt = 0;

public void threadAndLogTest2(){

logger.debug4Dev("ACE-T");

}

@Async

public void threadAndLogTest(){

cnt++;

System.out.println(cnt+"번째 호출!!");

logger.debug4Dev("TAEHA("+cnt+")=====>"+Thread.currentThread());

}

public void threadAndLogTest3(){

threadAndLogTest();

}

}




결 과 : 아래처럼 출력이 되어짐! 사실 앞쪽에 쓰레드 관련 key 내역이 찍힘! ㅋㅋ

1번째 호출!!

2번째 호출!!  

 [2014-01-22 10:27:57] [DEBUG] [root.threadAndLogTest():27] - TAEHA(2)=====>Thread[asyncExecutor-2,5,main]

 [2014-01-22 10:27:57] [DEBUG] [root.threadAndLogTest():27] - TAEHA(1)=====>Thread[asyncExecutor-1,5,main]

3번째 호출!!                 

 [2014-01-22 10:27:57] [DEBUG] [root.threadAndLogTest():27] - TAEHA(3)=====>Thread[asyncExecutor-3,5,main]

. . . . . . 계속 .. . . . .

 

<< 참고 사이트 >>

자바지기님이 좋은 고려사항을 써주셨다.

1) 참고 사이트 : http://slipp.net/questions/10

2) http://docs.spring.io/spring/docs/2.0.0/reference/scheduling.html

3) http://whiteship.me/?tag=async   // 역시 백기선님! @Async에 관한 좋은 내용들이 있다.

 

마지막으로 여러가지 테스트를 해보니..

@Async가 먹히지 않는 경우는 2가지가 있다.

1) @Autowired가 아닌 new로 했을 경우

    ex) Test Code에서 @Autowired AsyncThread asyncThread;가 아닌

          AsyncThread asyncThread = new AsyncThread(); 로 인스턴스를 만들어 호출하였을 때

         동작하지 않았다.(기능 X)

2) 같은 Class 내에 있는 Method에서 @Async Method를 호출 하였을 때! 동작하지 않았다.(기능 X)

   ex) Test Code를 조금 변경!  

public class AsyncAnnoTest {
 KTLogger logger = KTLoggerFactory.getLogger(AsyncAnnoTest.class);

 @Autowired AsyncThread asyncThread;
 
 @Test
 public void asyncAnnotationTest() {
  
  //AsyncThread asyncThread = new AsyncThread();
  int scope = 1000;  
  logger.debug4Dev("==============[start]===================");
  for(int i=0; i < scope; i++){ 
   asyncThread.threadAndLogTest2();
   //asyncThread.threadAndLogTest();
   //asyncThread.threadAndLogTest3();
   
  } 
  //asyncThread.threadAndLogTest2();
  logger.debug4Dev("==============[end]===================");
 }

} 

 

 Target Code

@Component
public class AsyncThread {
 
 private KTLogger logger = KTLoggerFactory.getLogger(AsyncThread.class);
 private static int cnt = 0;
 
 
 public void threadAndLogTest2(){
  logger.debug4Dev("ACE-T");
  threadAndLogTest();  // @Async Method를 호출!! => @Async 기능 X
 }
 
 
 @Async
 public void threadAndLogTest(){
  
  cnt++;  
  System.out.println(cnt+"번째 호출!!");
  logger.debug4Dev("TAEHA("+cnt+")=====>"+Thread.currentThread());
  
  
 }
 
 public void threadAndLogTest3(){
  threadAndLogTest();  
 }
 

} 

 

결과 : 쓰레드가 모두 동일하다.(녹색은 그냥 만든 Key 값이다.)

53ff4311-b39c-4b9f-b705-af55e2c8916a_1 [2014-02-06 13:38:30] [DEBUG] [root.threadAndLogTest():28] - TAEHA(988)=====>Thread[main,5,main]
53ff4311-b39c-4b9f-b705-af55e2c8916a_1 [2014-02-06 13:38:30] [DEBUG] [root.threadAndLogTest2():18] - ACE-T
989번째 호출!!
53ff4311-b39c-4b9f-b705-af55e2c8916a_1 [2014-02-06 13:38:30] [DEBUG] [root.threadAndLogTest():28] - TAEHA(989)=====>Thread[main,5,main]
53ff4311-b39c-4b9f-b705-af55e2c8916a_1 [2014-02-06 13:38:30] [DEBUG] [root.threadAndLogTest2():18] - ACE-T
990번째 호출!!
53ff4311-b39c-4b9f-b705-af55e2c8916a_1 [2014-02-06 13:38:30] [DEBUG] [root.threadAndLogTest():28] - TAEHA(990)=====>Thread[main,5,main]
53ff4311-b39c-4b9f-b705-af55e2c8916a_1 [2014-02-06 13:38:30] [DEBUG] [root.threadAndLogTest2():18] - ACE-T 

 

정상적이라면..Thread[asyncExecutor-2,5,main] 요런식으로 수행한 asyncExecutor 가 찍혀야 한다.

 


                                   - END -


반응형