티스토리 뷰
프로세스와 스레드
- 어플리케이션 구성 요소가 시작되면 안드로이드 시스템은 하나의 실행 스레드로 어플리케이션 서비스를 시작한다
- 기본적으로 같은 어플리케이션의 모든 구성 요소는 하나의 프로세스와 스레드에서 실행된다 (메인 스레드)
- 구성 요소가 시작되었는데 이미 해당 어플리케이션의 프로세스가 존재할 경우 해당 프로세스 안에서 같은 스레드를 사용한다
- 필요할 경우, 어플리케이션의 구성 요소가 다른 프로세스로 실행될 수 있고 프로세스에 스레드를 추가로 만들 수 있다
✔️ 프로세스
- 운영체제에 의해 메모리에 적재되어 실행중인 프로그램
✔️ 스레드
- 프로세스 내에서 실제로 작업을 수행하는 독립적인 주체
✔️ 멀티 스레드
- 하나의 프로세스 내에서 두 개의 스레드가 동작하는 것
메인스레드 (UI 스레드)
- 어플리케이션 실행 시 시스템에서 main()을 실행하여 만들어지는 프로세스에 자동 생성되는 스레드
- 안드로이드의 주요 컴포넌트가 실행되는 스레드이다
- UI를 그리고 갱신할 수 있는 유일한 스레드이기 때문에 UI 스레드라고 불린다
- 멀티 스레드 작업 시 다른 작업 스레드에서 UI 갱신이 필요할 경우 메인 스레드와의 통신을 통해 작업을 수행할 수 있다
✔️ 단일 스레드 모델
- UI 스레드를 차단하지 말 것
- UI 스레드 외부에서 Android UI 툴 키트에 접근하지 말 것
작업 스레드
- 시간이 걸리는 작업을 메인 스레드가 아닌 별도의 스레드에서 처리해준다
- 하지만 UI 갱신은 메인 스레드에서만 가능하므로 스레드 통신을 통해 작업 스레드의 내용을 메인스레드로 전달하여 UI 작업을 완료한다
✔️ 스레드 통신
- 하나의 스레드에서 다른 스레드로 데이터를 전달하는 것
Message
- 스레드 통신에서 하나의 데이터를 담는 객체
Runnable
- 데이터가 아닌 실행 코드를 담고있는 객체
- 실행될 코드를 Runnable의 run() 메소드 안에 작성하여 전달한다
Message Queue
- 스레드가 자기 자신 또는 다른 스레드에서 받은 Message 또는 Runnable 객체를 선입선출 형식으로 보관하는 Queue
Looper
- Message Queue에서 Message나 Runnable 객체를 꺼내 해당 객체와 연결된 Handler를 호출하여 전달하는 메세지 관리 클래스
- 메인 스레드에는 Looper가 기본적으로 구현되어 있으며 생성되어 있다
- 활성화된 Looper는 quit() 실행시 즉시 종료되며, quitSafely()로 종료 시 Message Queue의 Message를 모두 처리하고 종료된다
Handler
- Looper로부터 받은 Message를 처리하거나 다른 스레드로부터 Message 객체를 받아 Message Queue에 저장하는 통신장치
- Handler 객체는 하나의 스레드와 해당 스레드의 Message Queue에 종속되며 생성 시 자동으로 연결된다
- Message 전달 시 수신 스레드에 속한 핸들러의 post() 또는 sendMessage() 메소드를 호출한다
- 받은 Message 처리 방식은 handleMessage() 메소드로 구현한다
AsyncTask
- 하나의 클래스에서 UI와 백그라운드 작업을 할 수 있도록 안드로이드에서 제공해주는 클래스
- 작업 스레드에서 작업 수행 후 UI 스레드에 결과를 게시해주므로 우리가 스레드/핸들러 처리 작업을 해주지 않아도 된다!
- 하나의 클래스 안에 스레드 동작 부분과 UI 갱신 부분을 함께 구현하므로 가독성이 좋아진다
- AsyncTask를 확장하는 서브 클래스를 만들어 doInBackground() 메소드에 백그라운드 스레드 작업 내용을 구현한다
- UI 갱신을 위한 부분은 onPostExecute() 메소드에 구현하며 이 메소드는 메인 스레드에서 실행된다
- 메인 스레드에서는 execute() 메소드를 호출하여 AsyncTask 작업을 실행한다
✔️ 예시
- AsyncTask 클래스를 확장하는 InsertAsyncTask 클래스를 구현한다
- doInBackground() 콜백 메소드안에 백그라운드에서 실행될 내용을 구현한다
- Acvitivity에서 insert 함수를 호출하게 되면 execute() 메소드로 AsyncTask 작업을 실행한다!
class PlaceSearchRepository{
private val database = RecentPlaceDB.getInstance(EarlyBuddyApplication.getGlobalApplicationContext())!!
private val recentPlaceDao = database.recentPlaceDao()
fun insert(recentPlace: RecentPlaceEntity) {
InsertAsyncTask(recentPlaceDao).execute(recentPlace)
}
private class InsertAsyncTask<TE, TDO : BaseDao<TE>>(private val dao: TDO) : AsyncTask<TE, Void, Void>() {
override fun doInBackground(vararg entity: TE): Void? {
dao.insert(entity[0])
return null
}
}
}
정말 많은 것을 배울 수 있었던 포스팅이였다
적잘한 상황에 직접 코드로 멀티스레드를 적용해보고 그 내용도 포스팅할 수 있었으면 좋겠다〰️
🕊 참고자료
'Android' 카테고리의 다른 글
[Android & Kotlin] Intent로 Data Class 타입 객체 넘기기 (1) | 2020.08.21 |
---|---|
[Android] 안드로이드 Activity와 Fragment의 생명주기 (0) | 2020.06.23 |
[Android] 어플리케이션 기본 항목 - 4대 컴포넌트, App Manifest (0) | 2020.06.23 |
[Android & kotlin] AAC(Android Architecture Components) - Room (0) | 2020.06.22 |
[kotlin] DI 의존성 주입 - koin 사용하기 (0) | 2020.06.14 |