2020-02-08 TIL

할 일 목록

  • 코루틴 스터디 했던것 복습

완료하지 못한 목록

완료 목록

  • 코루틴 스터디 했던것 복습

5Fs

1. Fact

1. 코틀린

  • 우리는 표현을 yield처럼 해서 제어문처럼 표현했지만 얘는 사실 케이스 두개를 나눠서 3번 실행하는거랑 7번 실행하는거랑 나눠서 함수 2번 호출로 바꿔놓은 것임 컴파일러가
  • 이 두개가 한쌍인 함수인데 두번 호출한건데 세번 호출한거랑 7번 호출한걸로 그럼 이 한쌍인 함수를 함수 두개로 나누는것 보단 코드를 개편해서 함수 안에다가 스위치 구문으로 a 케이스 b 케이스를 만든다음 시스템이 이 함수를 호출할 때 케이스 a로 얘를 호출하고 다음번엔 케이스 b로 호출하면 된다.
  • 내가 a라는 함수를 호출할때 우리는 안보이지만 힌트를 넣어준것임 어떻게 분기할지 상태에 따라 이 함수는 케이스로 분리되서 다르게 실행되는 것임 .함수를 호출하는데 지속적으로 보내줘야하는 상태 이것을 continuation이다.
  • a를 호출할때 continuation의 상태를 1번으로 보냈다가 다음 a를 호출할 때 2번으로 보냈다가 하는 것임
  • 우리는 a를 호출할때 continuation이 stop인 상태에서 상태 1번으로 빠져서 실행하다가 스위치 a블록이 다 실행될때 continuation을 resume으로 바꾼 것임. 정확하게는 suspend를 건것임. continuation을 정지 상태로 만든것임.그러면 다음번에 다시 a 함수 호출할 때 continuation은 resume이 되는 상태가 되는것임. resume할때 아까 상태에 1을 더해서 2번이 되는것임. 그리고 나서 a를 호출할 때 continuation 객체를 넣어주면 이제 case 2번이 호출되고 다끝나고 나면 더이상 밑에 케이스가 없으니까 컴플리트로 빠짐 이 컨티뉴에이션이 완료되는거임
  • 컨티뉴에이션은 태어날때 suspend에 상태 0번으로 태어나고 a함수를 호출할때 마다 a함수 안에서 continuation count가 증가하면서 점점 상태가 resume되서 실행되다가 이 케이스가 끝날때 다시 suspend로 간다.
  • 그 다음번에 다시 a함수를 호출하면 continuation이 다시 2번으로 들어와서 케이스 2번 이 실행하다가 케이스 2번이 다 실행이 끝나면 다시 suspend로 멈춘다. 그러면서 카운트는 또 올라가고
  • 이걸 통해 동기문이지만 비동기처럼 끊어서 실행이 가능한것임. 우리가 짠 제어문을 그녀석이 스위치문으로 코드를 나눠주는거다. 우리는 우아하게 yield같은 키워드를 넣어 나눠준것. 컴파일러에게 알려준것.
  • yield를 두번 넣으면 코드가 2개 생긴다. 하지만 for문 안에서 넣었으면 얘가 실행하고 나서 continuation이 순차로 증가만 하는게 아니라 다시 0번으로 돌리면되
  • (continuation도 똑같이 if else처럼 분기도 할 수 있고 for문처럼 돌아갈 수도 있는 것임) 예제 필요
  • continuation 상태만 다시 올려주면 되니까 else일때 yield를 걸면 continuation이 내려오다가 continuation else 구문도 다른 케이스로 분리해서 if 일땐 7번으로 빠지지만 else일때 9번으로 빠지게 하면됨 7번이나 9번이 결국 10번으로 오게 하면됨.
  • for문도 계속 돌아가면 for문에 있는 조건들은 다 if문이다.while 안에 있는 것 처럼. 그 조건대로 조건을 만족하지않으면 다시 코드위로 보내는 컨티뉴에이션으로 상태 바꿔주면 계속 돌게됨. 그러다 가면 빠져나오는 쪽 컨디뉴에이션으로 바꿔주면 되고 .이걸 일일이 하는게 아니라 다 로직으로 만들어서 컴파일러가 한번에 컴파일 할꺼니까
  • 그래서 우리는 언어마다 다른 기능을 갖고 있는데 자바스크립트 같은 경우에는 제너레이터 function이나 async await이나 async iterable 을 사용한다고 선언하고 그 안에서 yield나 await을 걸면 거기가 바로 continuation의 switch 분기를 만들어주는 hint가 된다. 그럼 두가지 다 필요한거임.특정한 함수 블록을 선언했어 그안에 특정 키워드를 썼어 이걸로 얘는 컨티뉴에이션을 바꿔야 하는 애고 실행할떄 분기는 여기서 해야되 라는 힌트를 준거임. 그런데 비해 그런 언어들의 단점이 있음. 대표적으로 c샾과 자바스크립트. c샾의 단점은 컨티뉴에이션이 사용할때 언어에서 확정된 스펙으로밖에 컨티뉴에이션이 일어나지 않는다. async await 쓸때 외엔 c샾에서 continuation을 만들어 내는 블록은 없다.
  • 자바스크리트도 마찬가지제너레이터 또는 async await을 만들때 말곤, 특수한 언어가 정해져있는 케이스 외엔 절대로 cps를 언어가 지정되어져 있는 형태의 함수 구조 외에는 절대로 언어가 컴파일 할때 걔를 cps 스타일로 컴파일 해주지 않는다. 두번째 단점은 얘가 특정 키워드로 구분했는데 그렇단 얘기는 특정 키워드에 해당되는 관련 객체도 시스템 꺼다. 대표적으로 js의 async await을 써서 async await을 쓸때마다 promise가 확정된다.promise 객체는 자바스크립트 내장 객체다. 우리는 cps 할떄 커스텀 객체를 쓸 수 없게된다. 씨샾도 마찬가지 씨샾에서도 async await 쓰면 task란 객체가 있어서 얘가 확정임.얘내는 언어 스펙에 따라서만 continuation을 쓸 수 가 있음. 하지만 코틀린은 코루틴을 만들때 특정 스펙으로 구현하는걸 원하지 않았고, 아무 코드에서나 cps를 쓸 수 있고 cps대상 객체도 아무거나 쓸 수 있게 했음. 그러다보니 어려움 . 불친절하고. 밑의 코드(정확한거 아님) 바벨로 돌려보면 continuation만들고 switch문 분기 만들고 해서 바꿔줌.
generator func () {
    var a = 1
    yield(a)
    a++
    yield(a)
    a++
    yield(a)
}
  • 근데 이걸 컴파일러가 안해주고 우리가 불편하게 짠다면 어케할까 ? 우리는 이 함수가 컨티뉴에이션을 받는 함수라고 생각하고 짜겠음. 미친 스위치문까진 못쓰겠어 근데 여기는 컨티뉴에이션을 받는 인터페이스 cnt 있다 생각해보자. cnt를 상속받은 객체나 함수가 있다고 생각해보면 a함수에게 cnt를 넘기면 되겠네. 얘도 컨티뉴에이션을 받는 함수니까 그럼 여기서 대기를 타고 여기서 리턴으로 끊음.
  • 리턴 끊는건 언어가 해줄 수 있는건데 그래서 우리는 여기에 이렇게 넣는 함수를 만듬 컨티뉴에이션이 아닌 일반적인 문들도 넣을 수 있음. 근데 컨티뉴에이션이 나오면 컴파일러가 어디서 끊어주는 스위치를 여기서 나눠주는것. 그래서 얘내는 어떤 키워드에 대해서 스위치를 나눠주는게 아니라 컨티뉴에이션을 받는 타입의 함수가 나오면 그떄 끊어줌 . 그래서 키워드에 의존하는게 아니라 얘는 a함수 b함수 c함수가 가 suspend함수일때 얘내가 호출되는 시점에서 끊음.얘는 그럼 컨티뉴에이션을 직접 안받고 얘는 만들때 컨티뉴에이션을 받는 블록 함수를 리턴하도록 되어있음. 그럼 얘의 인자는 다른걸 받아도됨 얘는 그럼 반드시 컨티뉴에이션을 처리하는 블록함수의 리턴값을 리턴해야됨. 컨티뉴에이션을 만들어주는 제너레이터가 있는데 여기다 넣어주면 컨티뉴에이션 객체에 컨티뉴에이션 객체가 바로 인자로들어옴. 이함수는 무조건 c에 resume을 해줘야함.언제 해줄지는 내가 정할 수 있음. 앞의 언어들보다 불편하지만 특정 스펙에 의존 안한다. 그래서 suspend를 붙힌 객체에서는 continuation 객체를 줄거니까 . 그래서 operator도 suspend가 되는것임.
  • 코루틴을 만드는 방법은 suspend함수를 만들어서 continuation 블록을 만들어 내는거다 라고 생각하면됨 .
  • launch : 블로킹을 걸지 않음. 다른 별도 스레드에서 얘를 실행하면서 현재 이 흐름은 바로 제어권을 돌려줌. 그게 바로 얘임
  • runblocking : (컨티뉴에이션 블록)블록 전체가 다 실행되는 동안 나는 스레드를 블로킹 할거다라는 말임. 그래서 되도록이면 안써야됨. 이게 메인이니까 쓴거임 . 안에있는 작업 다 끝날떄 까지 함수로 종료 못시키게 하려고 쓴것임.
  • 크게보면 cps를 동작시키는 블럭 선언을 지금 두가지를 하고있는건데 runblocking과 launch
  • c를 쓰면 제어문을 멈출 수 있을 뿐만 아니라 내가 언제 c를 resume할지를 결정할 수 있음.사실은 제어문을 멈추는 것도 맞는데 비동기적으로 내가 전진 시키고 싶을때 전진시킬 수 있음. 제너레이터 같은 경우에 여기서 코드 실행하고 바로 리턴하거나 바로 전진을 시켰는데 만약 컨티뉴에이션 객체를 바로 여기서 리턴을 시키지 않고 promise 객체를 걸어서 promise안에서 c를 처리하고 그 다음번을 진행하게 할 수 있음.결국 중요한건 컨티뉴에이션을 호출해서 그다음 걸 호출할건지 말건지 결정하는것. 그래서 c resume을 여기서 필수적으로 해줘야 된다고 했는데 그 타이밍을 내마음대로 정할 수 있다는 것임. 왜 이함수가 호출되야 그다음번 으로 전진할태니까 시스템은 결국 a함수를 여러번 부를껀데 continuation resume이 일어났을때 부를것임.
  • delay 함수는 suspend 함수임 얘를 호출하고 나면 continuation의 resume이 1초뒤에 호출될것임. 사실 delay 함수가 호출되고 나면 cps에 걸려서 케이스 첫번째에서 멈춰있음. 그리고 1초 후에 continuation resume을 통해 그 밑에있는 두번쨰 케이스인 println이 호출된다. 그리고 나서 빠져나와서 끝남. yield같은 키워드가 아니라 얘는 suspend 함수를 만날때 마다 케이스를 분기한다. delay가 suspend 함수인 것임.delay에서 continuation resume을 할때 까지는 절대 다음번 케이스가 호출될일이 없다.
  • 그리고 그밑의 hello는 launch라고 했으니 바로 실행이 된다.그래서 1초 기다리않고 hello는 바로 진행.
  • 근데 만약 runblocking을 했지만 delay 2초를 안걸었으면 launch 안기다리고 끝나버렸을 것임 launch는 백그라운드 사정이고 runblocking은 메인의 사정이니까 종료됨.
  • 근데 delay 2 안써도 world가 찍히는데 이건 뒤에 원리를 설명 할것임.
  • launch도 suspend 블록임.얘의 launch의 보고를 기다리는 기능이 Runblocking 안에 있어서 그런다.자기 자식의 job이라고 부르는 건데 자식 job이 끝나야 부모 job도 끝남.
  • p.235 코드 밑에 getFact의 가장 큰 특징은 suspend가 걸려있다는 거다. 여기에 따로 continuation을 받지 않고 있음. 분명히 continuation resume을 해야된다고 이야기 했는데 그 이유는 얘한태 await이 걸려있기 때문이다. 이미 대신 continuation을 받아주는 객체를 내부에 생성했기 때문이다. async라는 함수가 생성했다. async라는 함수는 인자로 람다를 받아서 람다에 있는 애를 completedFuture 처럼 함수로 간직하고 있다. 아직 실행되고 있지 않은것임. 이 함수가 아직 실행되고 있지 않음. factClient.getFact()는 동기 명령인데 동기명령이니까 백그라운드에서 실행하는 동안에 현재 메인스레드를 차단하고싶지 않으면 백그라운드에서 얘를 실행함. 그래서 얘를 async로 감싸놨는데 async는 이 람다를 함수로써 갖고 있는거지 아직 실행한게아님. 언제 실행하냐면 await 시점에서 실행함. completedFuture와 비슷함. await 불리기 전까지 실행하지 않음. 하지만 Fact의 타입은 이때 확정된다. 람다의 반환타입을 통해서 변수의 반환타입을 컴파일러가 이미 추출할 수 있다. async는 어떤 타입을 반환하냐 함수가 반환할 타입을 제네릭으로 감싸고 있는 deffered를 반환함.이거 코틀린 타입임. 코틀린의 async에 반환하는 전용 타입임. deferred 타입이 갖고 있는 메소드가 await이다. await 함수는 자기의 람다블록을 백그라운드에 서 실행하는 명령임. 그때 차단이 일어남. 이 차단이 일어나는 동안 laucn를 걸었네 launch 안에서 차단이 일어나는 것임. 런치는 차단 했든 안했든 fact.await()을 바로 보내고 있음 밑에서 그럼 실행 순서가 launch 안에 있는 fact.await()이 가장 먼저 실행되고 그리고 return 에서 await()이 불릴 것임. 그러면 factRepository.insertFact()는 오래걸리는 말든 알아서 하고 있을 거고 근데 함수는 알다싶히 인자부터 해석되는데 함수의 결과를 기다리지 않을거지만 함수에 들어가는 인자는 바로 실행 됬을것임.그래서 await 함수로 빠졌을 것이다. 그래서 launch는 백그라운드 인데 백그라운드에서 await을 차단하고 있을 것임. return fact.await()을 할 경우 awiat을 차단하고 기다리고 있다가 그다음 리턴하게 됨.그럼 이 일이 뭘 일으키느냐면 이 fact의 resume타임을 일으킴 .이 getFact의 suspend가 풀리고 resume이 되는 타임이 바로 이 타이밍임 그래서 이걸 어떻게 자동으로감지하느냐 suspend 함수 안에서 다른 suspend 함수들을 부르면 continuation이 걔한태 위임해서 continuation에 대한 처리를 자동으로 위임해주는 기능. 이함수는 어짜피 continuation이 눈에 안보이지만 들어오거니까 그럼 여기 다른 서스펜드 함수는 뭐다 컨티뉴에이션꺼를 줄거란 말임. 컨티뉴에이션 블록 안에서 다른 컨티뉴에이션을 부르면 그함수의 컨티뉴에이션을 쓰는게 아니라 지가 갖고 있는 컨티뉴에이션을 준다. 그래서 여기서 continuation resume이 얘한태 위임된다. 이게 subjob이 성립하는 이유이다. subjob이 다 끝나야 mainjob이 끝나는 이유가 자기 블록에서 continuation이 생성되서 들어왔을거 아냐 시스템이 콜했을때 그 컨티뉴에이션이 물려줄것임. 그 함수만을 위해 새로운 컨티뉴에이션을 만드는게 아니라
  • 코루틴이 왜 성능이 좋냐면 스레드를 만들지 않기 때문이다 . 그럼 여기서 주의할 점은 자바 스크립트에서 async await을 엄청 쓰는데 정말 자바스크립트가 싱글 스레드임? 비동기 비차단. 근데 진짜 싱글스레드긴 해 ? 아님 근데 왜 성능이 좋다고 얘기함?
  • 우리가 ajax를 7개를 물면 싱글 스레드가 하나씩 처리할까 ? 그럼 백그라운드 스레드가 있는 거잔아 백그라운드 스레드가 7개 만들어졌으면 걔들 만들어서 어디에 보고한다? 메인 스레드에 보고할려고 그러는것임. 보고하는 스레드가 한군대인거다 !!!! 싱글스레드란 것은 정보 데이터가 모이는 곳이 한군대라는 것임.
  • 코루틴이 왜 빠른지 이야기를 하면 코루틴은 백그라운드 스레드를 여러개 만들려고 하지 않고 필요할때만 만듬. 그럼 얜 백그라운드 스레드가 여러개가 아닌데 어떻게 동시 처리를하지 ? suspend 단위로 나눠진걸 eventqueue에 넣어서 몇개의 스레드만 있어도 suspend block 단위로 놀고있는 스레드가 가져가서 처리하기 때문이다. 다른 스레드는 백그라운드 스레드가 다 끝날때 까지 그 스레드가 묵여있는것에 비해서 얘는 전체 작업이 전체 작업이 아님 나눠져 있는 suspend함수 block으로 되어져 있음. 그 블록을 놀고 있는 스레드가 잡아다 처리함.
  • 그래서 우리가 코루틴 혜택을 받으려면 suspend 함수를 잘게 잘라야함.
  • 그래서 어떤 스레드가 이 작업을 처리했으면 좋겠어란 개념이 있는데 a라는 스레드에게 서스펜트함수 3개를 동시에 시켜도 동시 실행처럼 보일것임. 마치 시분할 컴퓨터처럼 동시 실행으로 보일 것임. 왜냐 시분할 컴퓨터랑 똑같은짓 하기 때문이다. 이게 바로 스레드를 조금 쓰는데 멀티스레드처럼 보이는 이유이다. 스레드 하나가 자기한태 부여되 있는 여러 잡들을 서스펜드에 쪼개서 돌아가면서 실행한다. 그래서 시분할 처럼 보이는 것이다.
  • 사실 시분할이 아님 다 따로 해주는것과 똑같음 그럼 javascript 짤때랑 똑같음 setTimeout에 효과를 보려면 timeout에 들어갈 함수가 작아야 효과를 본다. 계속 전환이 될태니 만약 timeout에 루프 1억이 걸려있으면 절대 타임아웃 다음 타임아웃이 일어나지 않을것임. suspend가 굉장히 긴 함수를 실행하면 멀티스레드처럼 보이지 않을것임.
  • 왜 코루틴이 스레드를 많이 만들지 않고도 동시작업을 할 수 있는지에 대한 원리를 여태 이야기 한것임.
  • 원리가 뭐다 cps 스타일로 코드를 쪼개는데 그건 suspend 함수 기준이었고, 쪼개진 함수를 얘가 여러개의 잡이 있으면 돌아가면서 실행하기 때문에 하나의 스레드인데도 불구하고 동시 실행처럼 보인다 이것임. 이게 결국 코루틴의 원리임. 근데 어떤건 진짜 백그라운드 작업에서 하고싶다면 메인 스레드가 아니라 진짜 백그라운드에서 하고 싶다면 나는 현재 suspect 를 실행하는 실행기를 선택할 자유가 있음. 따라서 나는 dispatcher를 고를 수 있음. 이전까지는 dispatcher를 다 main을 고른거고 p.237 코드 애들은.
  • dispatcher를 포함하고 있는 dispatcher 외에도 여기서 오류가 나면 오류처리기도 있어야 하는데 dispatcher와 오류처리기를 합쳐서 context라고 부른다. 고유 명사임 coroutine context(dispatcher + 에러처리기).그래서 이걸 생략하면 기본 dispatcher 과 기본 에러처리기를 준다. 237 페이지 보면 인자 없이 launch로 다 보냈는데 생략하면 다 기본값으로 메인으로 간다. 여기엔 에러처리기와 디스패처를 넣을 수 있고 subjob도 넣을 수 있는데 그러면 부모잡이랑 서브잡하고 연결되서 서브가 끝날때 같이 끝나게 만들어줄 수 있음.
  • 스레드끼리 동기화를 못하는데 못해서 나온게 channel이다. suspended pattern으로 만들어진 스레드들이 동시에 쓰는 공간이 있음.dispatcher만 쓸 수 있고 다른애들은 읽을수만있음. 따라서 dispatcher만 쓰고 나머지 애들은 읽기밖에 못함. 채널은 코루틴 간에 critical section 없이 대화를 하기 위한것이다.
  • 코루틴은 시분할 컴퓨터 흉내내기임.
  • getFact는 무거운 것임 얘는 코루틴엔 없는 background 스레드가 하나 그냥 생성되는것임. 그래서 우리가 코드를 짤땐 continuation을 직접 resume 하는 경우는 거의 없고, 네이티브로 짤 경우에만 그렇게 할것임.
  • actor는 suspend 패턴을 객체화 시켜놓은것임.
  • cps는 바닥부터 배우는 코루틴 글 보면 된다.
  • 자바스크립트같은 fetch는 블로킹이고 무거워서 launch에 다 올리기 부담스러운디 launch.io라는 애한태 백그라운드로 보내는데 그 io에도 ajax를 몇개씩 걸기가 겁난다. 걔가 통으로 다 리턴할때까지 블로킹 할꺼니까 . 동시에 진행되는것 처럼 보이지만 첫번쨰 통신 다 끝나야 다음꺼 통신하고 그거 끝나야 다음 할 것임. 왜냐면 그떄 컨티뉴에이션이 나한태 들어오니까 스레드는 우리가 코루틴 블록을 발동시킬때 어떤 dispatcher 쓸지 결정할 수 있고 안하면 기본값이 들어갈 뿐이지 자동은 아님. 스레드의 개수 생성은 dispatcher의 타입에 따라 달리 생성됨. 이걸 singlemainthread를 dispatcher로 쓰고 있다면 얘는 아까 봤던 excutor pool을 쓰고 있다면 얘는 실행기가 3개일수 있음. 이 세개가 열심히 가져갈 수 있음. 여기가 싱글 스레드라면 열심히 힘내고 있겠지만, runblocking은 메인을 호출한 스레드가 블로킹 되는것이다. 메인을 호출한 함수가 블로킹 되는것임.
  • 사실 suspend함수 하나만 있어도 코루틴을 실행할 수 있는 컨텍스트를 만들어주고 발동하면 그냥 서스펜드 함수를 호출할 수 없음. 왜? 여기엔 cps를 처리해줘야되 라는 전처리에 대한 hint를 줘야하기 때문이다. 컴파일러에게 runBlocking이든 launch가 됬든 withContext가 됬든 뭐가 됬든 그런걸 coroutine Builder라고 부름.
  • coroutine scope는 cps 파싱을 컴파일라가 하는 공간이다 . 스위치문 나눠주는 공간 이동네 코드는 coroutine scope 이니까 이동네 코드는 컴파일러가 해석해서 스위치 구문 나눠주고 continuation으로 바꿔줘야되 라고 선언하는 이 공간 이게바로 coroutine scope.
  • 그래서 coroutine scope 안에서 suspend 함수를 써야지만 continuation의 혜택을 받음. 그러면 컴파일러에게 이동네는 코루틴스코프에여 라고 알려주는 지시가 필요한데 이걸 coroutine scope builder 라고 만듬.launch나 runblocking은 다 사실 중괄호 안에 coroutine scope를 만드는 것임. 컴파일러에게 알려주려고 . 코루틴 빌더는 코루틴 스코프를 만드는애임.이것 말고도 코루틴 스코프는 new coroutineScope해서 만들어도 된다.그 안은 cps스타일로 컴파일러가 인식한다.
  • 코틀린은 애너테이션 안쓰고 객체를 만들어서 컴파일러가 객체를 보고 판단한다. 문법이나 문을 키워드로 보는게 아니라 타입으로 보고 판단하는거다. 런타임 객체를 컴파일타임에 파싱해서 이동네 코든 내가 csp스타일로 파싱해놔야지 라고 하게되는것임.
  • 재귀는 그냥 값을 가지고 반환하는데 cps는 값을 바로 반환 안하고 함수를 계속 돌려주면서 함수 안에 있는 내용을 바꿔가면서 갱신함 마지막에 우리는 함수를 얻게됨 그 값을 들고 있는 함수를 얻게된다.그래서 재귀가 값을 재귀하지 않고 매번 함수를 만들어서 다음번 재귀한태 다른 함수를 넘겨주는 것임. 그함수가 어떤 함수다? 현재 결과를 저장하는 함수를 계속 만든다는것임.그래서 cps스타일로 재귀를 짜면 엄청무거워짐 함수를 매번 만들어서 . 하지만 우리는 그함수를 호출할 때 까지 지연시킬 수 있음. 더 심하게는 2번 재귀의 내용을 처리할 함수를 만들고 그다음번 재귀때는 이함수를 처리할 함수를 또 만들고 값은 하나도 없이 함수만 재귀수만큼 만들 수 있음. 우리가 이 함수를 실행하기 전까지는 다 지연이 가능함.함수형에서 cps는 재귀에대한 지연을 예약할 때 쓴다.
  • 우리는 다른 형태로 지금 쓰고 있음 제어문을 멈출 수 없는데 어떻게 제어문을 멈추는 형태로 바꿀까 더나아가 제어문을 멈출 수 있다면 다른 제어문과 이 제어문이 동시에 실행하는 시분할 처럼 흉내낼 수 없을까 더 나아가면 제어문을 멈출 수 있다면 재귀하는 시점을 비동기로 바꿀 수 있지 안을까? 이때 제어문이 멈췄는데 데이터 로딩이 끈난 이후에 재개하면 되지 않을까. 바깥쪽에서 보면 연속된 작업으로 보이지만 이 안에는 비동기를 껴넣을 수 있다.
fun main() = runBlocking {
    val jobs = List(10000) {
        launch {
            delay(1000)
            print('.')
        }
    }
    jobs.forEach{ job -> job.join()}
}

2.Feelings

  • 동시성에 대해서 깊게 공부 해봐야겠다.

3.Findings

4.Future Action Plan

  • 시간관리를 잘 해야겠다.

5.FeedBack


Written by@Zero1
This blog is for that I organize what I study and my thinking, feeling and experience.

GitHub