Android

Android 05. 동기(Synchronous) & 비동기(Asynchronous)

shin96bc 2022. 5. 26. 16:01

(1) 동기( Synchronous )

     1) 동기란 작업을 수행하고 그 작업이 완료될 때까지 다른 작업을 하지 못하고 기다리는 방식입니다.

 

(2) 비동기( Asynchronous )

     1) 비동기란 어떤 작업을 수행하지만 완료와 상관없이 계속해서 작업을 할 수 있는 방식입니다.

 

     2) 비동기가 필요한 이유

          <1> 첫번째 이유는 예를 들어 A 라는 애플리케이션에 다운로드와 페이지 닫기 라는 두개의 버튼이

                  존재한다고 가정했을 때, 두개의 버튼 모두 Main Thread 가 수행하도록 설계했다면 사용자가

                  다운로드 버튼을 누르는 순간 Main Thread 가 다운로드 작업을 시작하게 되고

                  페이지 닫기 버튼은 먹통이 될 것입니다.

                  Thread 는 작업을 순서대로 하나씩 처리하기 때문에 그렇습니다.

                  즉, 사용자가 보고있는 화면이 먹통이 되지 않게 하면서 여러가지 일을 동시에 처리해야

                  할 때 새로운 Thread 를 생성해서 비동기 처리를 합니다.  

        

          <2>  두번째로는 Main Thread 에서 5초 이상의 작업을 실행하면 ANR(애플리케이션 응답없음) 이

                  발생하게 됩니다. 그럴 때 비동기 방식을 사용하여 새로운 Thread 를 생성하고

                  무거운 작업은 새로운 Thread 에게 맡겨서 비동기 처리를 합니다.

 

          <3>  세번째 이유는 안드로이드에서는 초당 60프레임을 지원하는데, UI를 그리는 작업 중 한

                  프레임을 16ms 내에 그려내지 못하면 jank(프레임 누락으로 인해 끊겨 보이는 현상)가

                  발생합니다. 이런 jank 현상을 해결할 때도 비동기 방식을 사용합니다.

                  그러나 UI 관련 작업은 Main Thread 에서만 가능하기 때문에 UI 관련 작업을 비동기로 할 때는

                  Handler 가 필요합니다.

 

     3) 비동기 처리 방법

          <1> AsyncTask ( Class )

               1> AsyncTask 는 Main Thread 의 작업을 좀 더 효율적이게 해줄 수 있는 Background

                   처리 기법입니다.

               2> AsyncTask 는 작업 수행 시간이 수 초간 진행될 때 유용하며, 오랜시간 작업을 

                    해야하는 경우에는 AsyncTask 가 아닌 다른 방법을 권장합니다.

               3> AsyncTask 의 메서드

                    1. onPreExecute()

                         - 작업이 실행되기 전에 UI Thread 에서 호출됩니다.

                         - 이 단계는 일반적으로 사용자 인터페이스에 진행률 표시줄을 표시하며,

                            작업을 설정하는데 사용합니다.

 

                    2. (String) doinBackground(Integer integer)

                         - onPreExecute() 가 실행을 마친 직후 Background Thread 에서 호출됩니다.

                         - 이 단계는 가장 핵심적인 작업을 수행하는데 사용합니다.

 

                    3. onPostExecute(String result)

                         - Background 작업( doinBackground() )이 끝난 후에 UI Thread 에서 호출됩니다.

                         - doinBackground() 리턴값을 매개변수로 받아 처리합니다.

 

                    4. onCancelled(String result)

                         - doinBackground() 수행 중이나 Main Thread 에서 cancel(true)를 호출하면 

                            onPostExecute() 가 호출되는 대신 이 메서드가 호출됩니다.

 

                    5. onProgressUpdate(Integer integer)

                         - doinBackground() 수행 중에 publishProgress() 를 호출하면 호출되며, 주로 

                           작업의 진행 상태를 프로그래스바로 표시하기 위해 사용합니다.

출처:&nbsp;https://mailmail.tistory.com/12

 

               4> AsyncTask 주의점

                    1. AsyncTask 수행을 위해 생성된 객체는 execute() 를 통해 단 한번만 실행이 가능합니다.

                        (재 실행시 예외가 발생합니다)

 

                     2. AsyncTask 는 Main Thread 에서만 실행되고, 호출되어야 합니다.

 

                     3. MainActivity 가 destroy 되었을 경우를 대비해야한다. 만약에 아무런 처리를 하지 않았다면,

                         MainActivity 가 destroy 되어도 AsyncTask 는 Background 에서 계속 작업을 수행합니다.

                         그리고 작업이 완료되면 그 결과를 MainActivity 로 넘겨주려 할 것인데, MainActivity 는

                         이미 destroy 되었기 때문에 Activity 를 컬렉트 할 수 없어 메모리릭이 발생합니다. 

                         또한 화면 회전에 의해 Activity 가 destroy 되고 새 인스턴스로 create 되었을 때도 이와같은

                         상황이 발생할 수 있습니다.

 

                         그러므로 이를 위한 대비를 해야하며, cancel() 을 통해 doinBackground() 실행 완료 후,

                          onPostExecute() 가 호출되는 것을 막고, onCancelled() 를 호출하도록 해야합니다.

 

                     4. AsyncTask 를 여러개 실행하면 하나씩 순차적으로 진행되는데, 이를 동시에 처리하려면,

                         execute() 대신 executeOnExecutor() 라는 메서드를 사용하면 병렬처리가 가능합니다.
                         (순서는 보장되지 않습니다.)

 

          <2> RxJava ( Class )

 

          <3> Coroutine ( Class ) ( Kotlin )

 

     4) 비동기와 멀티스레드의 차이점

          <1> 멀티 스레드는 대부분 비동기 방식과 같이 구현되기 때문에  비동기 처리와 멀티스레드는

                  같다고 착각하기 쉽지만 사실은 다릅니다.

          <2> 그 이유는 멀티스레드와 싱글스레드 모두 동기 처리도 가능하고 비동기 처리도 가능하기

                  때문입니다. 즉, 스레드를 여러개 사용했다고해서 비동기 처리가 되는 것은 아니라는 것입니다.

                  (물론 멀티 스레드를 비동기 방식으로 구현했다면 큰 차이가 없습니다.)

          <3> 만약에 멀티 스레드를 동기로 구현했다고 한다면, 스레드는 여러개지만 결국 순서대로 하나씩

                  진행되므로 여러가지 일을 동시에 진행하는 비동기 방식과는 거리가 멀다고 할 수 있습니다.

                  (동기식 멀티스레드는 효율이 굉장히 나쁩니다.)

          <4> 비동기 프로그래밍 사진

출처:&nbsp;https://jayhyun-hwang.github.io/2021/09/02/The-Difference-Between-Asynchronous-And-Multi-Threading/

          <5> 멀티 스레드 프로그래밍 사진

                 

출처:&nbsp;https://jayhyun-hwang.github.io/2021/09/02/The-Difference-Between-Asynchronous-And-Multi-Threading/

 

          <6> 위의 사진과 같이 멀티스레드 프로그래밍은 여러 다른 함수들을 동시에 실행하는 것이고,

                  비동기 프로그래밍은 여러 함수들이 mom-blocking 으로 실행되는 것임을 알 수 있습니다.

          <7> 그리고 비동기적 이라는 것은 싱글 스레드, 멀티 스레드 모두에게 적용될 수 있습니다.

          <8> 정리하면 멀티 스레드는 작업자( Thread )에 관한 것이고, 비동기는 직업( Task )에 관한 

                  것임을 알 수 있습니다.

 

 

참고자료:

 https://mailmail.tistory.com/12

 

 https://jayhyun-hwang.github.io/2021/09/02/The-Difference-Between-Asynchronous-And-Multi-Threading/