쓰레드란?
=> 프로세스 내에서 순차적으로 실행되는 실행 흐름의 최소 단위이다.
프로세스?
=> 운영체제에 의해 메모리에 적재되어 실행 중인 프로그램.
=> 스레드로 구성
=> 모든 프로세스엔 1개 이상의 스레드가 존재하여 작업 수행.
=> 하나의 프로세스 내에 2개 이상의 스레드가 동작하도록 하는 것을 멀티스레드 프로그래밍
멀티스레드
=> 하나의 프로세스 내 둘 이상의 쓰레드가 동시에 작업 수행하는 것
=> 각 쓰레드가 자신이 속한 프로세스의 메모리 공유
=> CPU의 코어 수보다 더 많은 쓰레드가 실행되면, 각 코어가 정해진 시간 동안 여러 작업 번갈아가며 수행
=> 각 쓰레드가 서로 교체될 때 쓰레드 간의 문맥 교환(context switching)이 발생
=> Context Switching은 현 작업 상태나 다음 작업에 필요한 각종 데이터를 저장하고 읽어오는 작업
메인쓰레드
=> 쓰레드는 프로세스 실행 중 언제든 필요에 따라 만들어지고 실행된다. (기존에 이미 실행 중인 쓰레드에 의해 수행될 수 있음)
=> 프로세스가 시작될 때 최초의 실행 시작점부터 순차적으로 진행되는 실행 흐름을 메인 쓰레드.
=> 새로운 쓰레드가 오직 메인 쓰레드에 의해서만 실행될 수 있는 것은 아님.
Android UI Thread
=> 안드로이드 메인 쓰레드가 UI Thread
=> 화면에 그려지는 UI 관련 작업들은 UI Thread에서만 실행되어야 함
=> 메인 쓰레드는 메시지 큐 수신을 대기하는 Looper를 가지며, 사용자 입력과 시스템 이벤트, 화면 그리기 등의 메시지가 수신되면 각 메시지에 매핑된 핸들러의 메서드 실행
=> 메인이 아닌 Thread에서 UI관련 작업을 수행하려면, Handler를 통해 Main Thread로 메시지를 전송하고 해당 작업을 메인 쓰레드에서 처리해야 함
- 일반 쓰레드는 루퍼를 갖지 않고,
HandlerThread를 생성하면 Looper를 갖는 Thread 생성 가능 - Thread는 Thread 외부에서 전달된 message등이 인입되는 Queue를 가진다.
- Looper는 Queue에 message 혹은 Runnable 객체가 있다면 Handler로 전달한다.
- Handler는 Looper가 보낸 message 혹은 Runnable(쓰레드를 전달) 객체를 처리한다.
Handler
=> 안드로이드 OS에 메시지를 던질 수 있는 객체
=> 핸들러를 통해 쓰레드 간 메시지를 주고 받을 수 있음
runOnUiThread
=> 수행하고자 하는 코드를 Main Thread가 처리하도록 하는 메서드
=> Handler와 마찬가지로 별도 생성한 Thread에서 UI 작업이 필요한 경우 사용
=> 개발자가 만든 Runnable 객체를 메인 스레드에서 실행되도록 만드는 메서드
=> 내부동작은, 현 스레드가 메인 스레드인지 검사해
메인 스레드가 아니면 post()
메인 스레드면 Runnable의 run() 실행
=> Runnable 객체에 구현된 코드를 반드시 메인 스레드에서 실행해야 할 때 사용하는 메서드
AsyncTask
=> 비동기작업 수행 위해 사용
=> 크기가 큰 파일 복사, DB 쿼리, HTTP 서버 API 요청, FTP 파일 다운롣 ㅡ등 비동기 작업 필요한 경우 사용
=> Thread, Handler, Message, Runnable 등 직접 다루지 않아도 메인 쓰레드와 별개로 비동기 실행이 필요한 작업에 사용
=> AsyncTask는 API Level 30에서 deprecated
AsyncTask 총 4단계
- 실행(execute) : 비동기작업 준비 & 시작
- 백그라운드 작업(doInBackground) : 백그라운드 쓰레드에서 비동기 작업 실행
- 진행 상황 업데이트(onProgressUpdate) : 백그라운드 쓰레드 진행 상황을 메인 쓰레드로 전달
- 비동기 실행 완료 후 처리(onPOstExecute) : 백그라운드 쓰레드 완료 후 메인 쓰레드에 완료 상태 전달0
쓰레드 오류상황
inner class ThreadClass : Thread() {
override fun run() {
while(isRunning) {
sleep(100)
Log.d(TAG, System.currentTimeMillis().toString())
binding.helloTextview.text = System.currentTimeMillis().toString()
}
}
}
android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
뷰 계층을 생성한 원래 쓰레드만이 해당 뷰를 조작할 수 있다.
메인 쓰레드가 아닌 다른 쓰레드에서 화면을 그리는 기능이 실행되었기 때문에 발생한 에러
해결방법
UI Thread와 Handler를 사용.
inner class ThreadClass : Thread() {
override fun run() {
val handler = Handler(Looper.getMainLooper())
while(isRunning) {
sleep(100)
handler.post{
binding.helloTextview.text = System.currentTimeMillis().toString()
}
}
}
}
핸들러를 사용 (메인에게 요청.)
'안드로이드 > 정리' 카테고리의 다른 글
[Android] Jetpack에 관해... [ ViewModel ] (0) | 2021.10.27 |
---|---|
[Android] Coroutine에 관해... (0) | 2021.10.21 |
[Android] 센서에 관해... (with camera) (0) | 2021.10.20 |
[Android] Firebase에 관해... (0) | 2021.10.18 |
[Android] ContentResolver, ContentProvider에 관해 (0) | 2021.10.12 |