설명하는 시나리오에서 클래스 java.util.concurrent.CyclicBarrier
의 인스턴스 사용을 권장 할 수 있습니다 - 일부 계산을 비동기 적으로 수행하는 다음 간단한 예제를 참조하십시오 (여기서는 "백분율 완료"값을 50으로 설정 한 다음 ~ 100), "percentage done"값을 주 스레드에서 검색 할 수 있습니다. 나는 내 SUT (또는, 당신이 좋아하는 AOP 프레임 워크를 사용할 수있는)의 두 가지 계산 방법을 가로 채기 위해 Mockito 스파이로의 JUnit 4를 사용
public class AsyncProcess implements Runnable {
private int percentageDone = 0;
public int getPercentageDone() { return percentageDone; }
public void doFirstHalf() { percentageDone = 50; }
public void doSecondHalf() { percentageDone = 100; }
public void run() {
doFirstHalf();
doSecondHalf();
}
}
단위 테스트이 들어 :
다음은 SUT 클래스입니다.
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.doAnswer;
import java.util.concurrent.CyclicBarrier;
import org.junit.Test;
import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
public class AsyncProcessTest {
@Test
public void testExecute() throws Exception {
final CyclicBarrier firstHalfStarted = new CyclicBarrier(2);
final CyclicBarrier firstHalfFinished = new CyclicBarrier(2);
final CyclicBarrier secondHalfStarted = new CyclicBarrier(2);
final CyclicBarrier secondHalfFinished = new CyclicBarrier(2);
AsyncProcess process = Mockito.spy(new AsyncProcess());
doAnswer(new Answer() {
public Object answer(InvocationOnMock invocation) throws Throwable {
firstHalfStarted.await();
invocation.callRealMethod();
firstHalfFinished.await();
return null;
}
}).when(process).doFirstHalf();
doAnswer(new Answer() {
public Object answer(InvocationOnMock invocation) throws Throwable {
secondHalfStarted.await();
invocation.callRealMethod();
secondHalfFinished.await();
return null;
}
}).when(process).doSecondHalf();
new Thread(process, "AsyncProcess").start();
assertThat(process.getPercentageDone(), is(0));
firstHalfStarted.await();
firstHalfFinished.await();
assertThat(process.getPercentageDone(), is(50));
secondHalfStarted.await();
secondHalfFinished.await();
assertThat(process.getPercentageDone(), is(100));
}
}
이 접근 방식을 사용하면 관련된 스레드의 실행 흐름을 매우 세밀하게 제어 할 수 있습니다. CyclicBarriers 쌍을 캡슐화하고 인터 셉션 호출을 추출하고 시간 초과 및 적절한 예외 처리를 지원함으로써 "마이크로 프레임 워크"로 쉽게 확장 할 수 있습니다.
[Awaitility] (https://github.com/awaitility/awaitility) 및 [ConcurrentUnit] (https://github.com/jhalterman/concurrentunit)의 두 가지 도구가 도움이 될 수 있습니다. – Jonathan