Android Multithreading

javaandroidmultithreading

Contents

  1. Android Threads

    • 1.1. UI, Binder, Background Thread
    • 1.2. Blocking UI Thread and ANR
  2. MultiThreading

    • 2.1. Basic Usage
    • 2.2. Multithreading Considerations
    • 2.3. Thread Safety
    • 2.4. Task Execution Strategies
    • 2.5. MultiThreading on Android : UI Thread Only
  3. Thread Communication in Java

    • 3.1. Pipes
    • 3.2. Shared Memory
    • 3.3. Blocking Queue
  4. Thread Communication in Android

    • 4.1. Android Message handling Mechansim
    • 4.2. MessageQueue
    • 4.3. Message
    • 4.4. Looper
    • 4.5. Handler
    • 4.6. HandlerThread
  5. Asynctask

    • 5.1. Overall
    • 5.2. Usage
    • 5.3. Pitfalls
  6. Executor
  7. IntentService
  8. Loader
  9. Select MultiThreading Method

안드로이드 애플리케이션을 개발하다 보면 비동기 작업이나 UI 반응을 위해 스레드를 사용할 일이 많이 생긴다. 안드로이드에서는 멀티스레딩을 위해 몇 가지 방법을 제공하고 있으며, API 문서만 읽고도 손쉽게 적용할 수 있게 되어 있으나 자세하게 정리하고자 이 글을 작성하였다.

1. Android Threads

안드로이드 애플리케이션이 시작되는 과정을 살펴보면, Linux Process를 만들고, 그 위에 Dalvik VM runtime을 띄워 Application Class의 Instance를 생성, Instance가 가지고 있는 Entry Point Component를 실행한다. 이 과정에서 Linux Process와 Dalvik VM을 관리하는 많은 스레드들이 생성되는데, 이 중 UI thread와 Binder thread는 Application에서 사용되며, Application이 자체적으로 Background thread를 만들어 사용할 수도 있다.

1.1. UI, Binder, Background Thread

안드로이드 애플리케이션에서 사용하는 모든 스레드는 Linux native pthread(POSIX Thread)의 자바 구현체이다. 하지만 Android Platform은 역할에 따라 UI, Binder, Background thread로 나누어 각각에 특별한 속성들을 부여했다.

UI Thread는 간단히 말하면 Main thread이다. 애플리케이션이 시작되어 프로세스가 종료될 때까지 유지되며, UI elements에 접근할 수 있는 유일한 스레드이다. (모든 Thread는 Linux native thread로 Linux에서는 동등하게 취급되기 때문에 Application Framework Layer의 WindowManager에서 UI thread 이외의 접근을 제한한다) Activity에서 실행하는 코드들은 별다른 스레딩을 하지 않았다면 UI thread에서 실행된다. UI elements들의 이벤트들을 순차적으로 처리하기 때문에 시간이 오래 걸리는 이벤트를 실행하면 UI 전체가 멈추게 된다.

Binder Thread는 IPC(InterProcess Communication)를 위한 스레드로, 모든 프로세스는 Binder thread를 위한 thread pool을 가진다. 이 스레드풀은 임의로 제거되거나 생성할 수 없으며, Intent, Content Provider, Service 등 다른 프로세스의 요청을 핸들링하게 된다. Binder를 사용할 경우를 제외하고는 생각하지 않아도 되는 thread로, Binder란 Linux IPC를 대체한 안드로이드 커널만의 프레임워크로, 프로세스 간의 RPC(Remote Procedure Calls)를 제공하는 것인데, 추후에 다른 글에서 다루기로 한다.

Background Thread는 애플리케이션이 필요할 때 생성하는 thread로 UI thread의 속성들을 상속받는다. 자유롭게 생성하고 실행이 가능하며, 일반적인 애플리케이션을 개발할 때 가장 신경써야 할 thread이다. 앞으로 다룰 Threading에 관한 내용은 거의 Background Thread에 대한 내용이라고 볼 수 있다.

1.2. Blocking UI Thread and ANR

사용자와 인터렉션하는 GUI 애플리케이션들의 경우, 사용자경험 측면에서 즉각적인 응답을 주는 것이 매우 중요하다. 사용자는 화면이 멈추고 아무런 입력도 할 수 없는 상태가 자주 일어나는 애플리케이션에 결코 좋은 평가를 하지 않을 것이다. 이런 이유로 윈도우의 ‘응답 없음’과 같이, 어떤 이벤트가 발생한 후 일정 시간동안 응답이 없는 경우 OS단에서 앱을 중지할 것인지 물어보는 (과격한) 정책들이 사용되고 있다.

Android에서는 UI Thread가 UI elements들의 이벤트들을 순차적으로 실행하는 까닭에 어떤 element의 이벤트가 오랜 시간 실행된다면 전체 UI가 다른 이벤트를 받지 못하고 멈추게 된다. 이 상태로 약 5초가 지나면 Android OS는 ANR(Application Not Responding) 메시지를 띄우며 사용자가 앱을 종료할 것인지 묻게 된다. 이 때 사용자가 당신의 애플리케이션이 완벽하다는 믿음을 가지고 종료하지 않고 기다려 주는 경우는 사용자가 당신 혹은 당신의 동료일 경우 뿐이다. 대부분의 사용자는 망설이지 않고 종료 버튼을 누를 것이며, 다시는 당신의 애플리케이션을 이용하지 않을 확률이 높다.

이 경우 사용자에게 비현실적인 것을 기대하기보다는 Background Thread를 사용해 비동기적으로 처리해 주고, 기다리는 동안은 처리되고 있다는 알림을 - 필수는 아니지만 - 띄우는 편이 사용자에게 더 큰 만족감을 줄 것이다. 더 나아가 안드로이드는 시간이 많이 걸리는 작업들 - 네트워크 등(더 찾아보기) - 을 Background Thread에서 처리하도록 (찾아봐야댐)버전 몇부터는 정책적으로 강제하였다. 다시 말해 Background Thread을 사용해야 하는 부분은 안드로이드 개발에 있어 빼놓을 수 없는 부분이며, Android MultiThreading에 대한 깊은 이해가 필요하다고 볼 수 있다.

2. MultiThreading

안드로이드의 스레드에 대해 더 살펴보기 전에, 기본적인 스레드에 대해 더 알아보자. 스레드란 프로세스 내에서 실행되는 흐름의 단위를 뜻하는 말로, 코드의 실행 흐름을 새로 만들 때 사용된다. 일반적으로 한 프로세스는 하나 이상의 스레드를 가지는데, 한 스레드 안에서 코드는 항상 순차적으로 실행된다.

(이 글은 작성 중이며, 이후 내용은 비공개 노트에 있습니다.)


Back to blog