728x90
@Test
fun `코루틴은 논블로킹으로 실행된다`(){
/*
코루틴 내부의 코루틴은 각각 논블로킹으로 처리된다.
단, 스레풀에서 돌렸을 때 이야기..
메인스레드 하나에서 돌리면 작업자가 한명이니 당연히 순차처리된다.
*/
runBlocking(Dispatchers.IO) {
launch {
repeat(1000){
println("1111111")
}
}
launch {
repeat(1000){
println("2222222")
}
}
}
}
@Test
fun `코루틴은 기본적으로 예외가 부모로 전파된다`(){
/*
예외가 부모로 전파되면 부모가 취소되고 결국 다른 형제 코루틴도 취소된다.
launch, async 동일
*/
runBlocking(Dispatchers.IO) {
launch{
repeat(100){
println("첫번째 $it")
if(it == 2){
throw RuntimeException("1111111 Error")
}
}
}
launch {
repeat(100){
println("두번째 $it")
}
}
}
}
@Test
fun `예외를 부모로 전파하지 않으려면 SupervisorJob을 사용해야 한다`(){
runBlocking(Dispatchers.IO) {
launch(SupervisorJob()) {
repeat(100){
println("첫번째 $it")
if(it == 2){
throw RuntimeException("1111111 Error")
}
}
}
launch {
repeat(100){
println("두번째 $it")
}
}
}
}
@Test
fun `예외를 부모로 전파하지 않는 방법으로 코루틴 내부를 try catch 로 래핑하는 방법도 있긴하다`(){
runBlocking(Dispatchers.IO) {
launch {
try{
repeat(100){
println("첫번째 $it")
if(it == 2){
throw RuntimeException("1111111 Error")
}
}
}catch (e: Exception){
println("캐치함 ${e.message}")
}
}
launch {
repeat(100){
println("두번째 $it")
}
}
}
}
@Test
fun `하지만 코루틴 바깥에 정의된 try catch 에서는 예외를 잡지 못한다`(){
/**
* async 도 마찬가지다.
* 이러한 특성 때문에 try catch 로 예외 전파를 막으려면
* 모든 코루틴 내부를 try catch 로 래핑해야 하는 문제가 생긴다.
*/
runBlocking(Dispatchers.IO) {
try{
launch {
repeat(100){
println("첫번째 $it")
if(it == 2){
throw RuntimeException("1111111 Error")
}
}
}
}catch (e: Exception){
println("캐치함 ${e.message}")
}
launch {
repeat(100){
println("두번째 $it")
}
}
}
}
@Test
fun `supervisorScope 블록을 이용하면 해당 블록 내의 코루틴은 모두 SupervisorJob을 사용하게 된다`(){
runBlocking(Dispatchers.IO) {
supervisorScope{
launch{
repeat(100){
println("첫번째 $it")
if(it == 2){
throw RuntimeException("1111111 Error")
}
}
}
launch {
repeat(100){
println("두번째 $it")
}
}
}
}
}
/**
* 예외전파는 SupervisorJob 으로 막았는데 핸들링은 어떻게 할 수 있을까?
* 예외를 핸들링 하려면 어쨋든 예외를 잡아야 한다.
*/
@Test
fun `launch 에서 발생된 예외를 캐치하려면 CoroutineExceptionHandler 람다를 사용해야 한다`(){
runBlocking(Dispatchers.IO) {
supervisorScope{
launch(
CoroutineExceptionHandler{context, ex ->
println("${ex.message} 에 대한 후처리입니다")
}
){
repeat(100){
println("첫번째 $it")
if(it == 2){
throw RuntimeException("1111111 Error")
}
}
}
launch {
repeat(100){
println("두번째 $it")
}
}
}
}
}
@Test
fun `async 에서 발생된 예외는 await() 호출시 try catch 로 캐치하면 된다`(){
runBlocking(Dispatchers.IO) {
supervisorScope{
try {
async{
repeat(100){
println("첫번째 $it")
if(it == 2){
throw RuntimeException("1111111 Error")
}
}
}.await()
}catch(e: Exception){
println("${e.message} 에 대한 후처리입니다")
}
launch {
repeat(100){
println("두번째 $it")
}
}
}
}
}
728x90
'Backend > Kotlin' 카테고리의 다른 글
Kotest 삽질기록 (0) | 2022.10.29 |
---|---|
[Kotlin] 생성자 매개변수 선언시 val, var (0) | 2022.09.02 |
[Kotlin] SpringMVC WebClient 에 Resilience4j 적용하기 (0) | 2022.05.10 |
[Kotlin] WebClient 에 동기식으로 사용하기 (0) | 2022.05.10 |
[Kotlin] thread-safe Collection (0) | 2022.04.14 |