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 { @Autowired AsyncThread asyncThread; } |
Target Code
@Component } |
결과 : 쓰레드가 모두 동일하다.(녹색은 그냥 만든 Key 값이다.)
53ff4311-b39c-4b9f-b705-af55e2c8916a_1 [2014-02-06 13:38:30] [DEBUG] [root.threadAndLogTest():28] - TAEHA(988)=====>Thread[main,5,main]
정상적이라면..Thread[asyncExecutor-2,5,main] 요런식으로 수행한 asyncExecutor 가 찍혀야 한다. |
- END -