안드로이드 Thread란

ee·2024년 5월 6일

Android

목록 보기
2/10

Thread

Thread란??

Thread란 동시에 여러 작업을 수행하기 위해 사용되는 개념이다

Android는 앱 구성하는 여러 컴포넌트들이 각자의 프로세스를 생성할 수 있고, 어느 프로세스에서나 메인 스레드 외의 추가 스레드를 생성할 수 있다.
우리가 일상생활에서 빨래를 돌려 놓고 외출을 하거나 배달을 시켜놓고 게임을 하듯이, 프로세스 내에서도 여러 작업을 동시에 가능케 하는게 Thread이다.

Main Thread

Main Thread는 프로세스가 실행 후 기본 실행을 담당하는 최초의 스레드라고 할 수 있다.

또한 Main thread는 UI작업을 담당하는 스레드이다. 오직 Main thread에서만 UI와 상호작용할 수 있다.
UI작업이 Main thread에서만 이루어지는 이유는 우리가 앱과 상호작용할 때는 순서대로 진행되어야 하기 때문이다. 예를 들어 우리가 이미지 생성 버튼을 클릭하고 이미지를 그리고 다시 완료 버튼을 클릭했다고 치자. 이 작업들이 여러 다른 스레드로 작업을 한다면 순서가 보장되지 않고 실행되어지기 때문에 우리가 원하는 이미지를 그릴 수 없을 것 이다. 따라서 오직 Main Thread에서만 UI와 상호작용한다.

Worker Thread

Main Thread에서 서버 통신이나 파일I/O, 데이터베이스 쿼리를 실행한다면 이 작업들이 끝날 때까지 전체 UI가 차단이 된다. 따라서 다른 스레드에서 이 작업들을 처리하는 데 이를 Worker Thread라고 한다. Main Thread에서 UI작업을 처리하고 Worker Thread에선 다른 일을 하도록 하여 UI와 차단을 방지한다.


class A: Thread(){
        override fun run() {
            super.run()
            for (i in 1..1000){
                Log.d("test", "first : $i")
            }
        }
    }

val a = A()
a.start()

Thread 클래스를 상속하여 run함수 안에 실행할 코드를 적는다.

Handler

Handler는 스레드간 통신을 가능케 하는 클래스이다.

주로 메인 스레드와 백그라운드 스레드 사이에서 작업을 조정하고 특정 작업을 예약하거나 지연시키는 데 사용된다.
만약 Worker Thread에서 UI작업을 해야한다면??
백그라운드 스레드에서는 UI를 직접 조작할 수 없으므로 Handler를 사용하여 Main Thread에 작업을 전달하여 UI업데이트를 수행한다. 또한 Handler를 사용하여 작업을 예약하거나 지연시킬 수 있으므로 앱의 응답성을 향상시킬 수 있다.

val handler = Handler(Looper.getMainLooper())

Thread{
	for (image in imageList){
    	handler.post{
        	binding.iv.setImageResource(image)
        }
        Thread.sleep(2000)
    }
}.start()

worker thread에서 UI를 업데이트 시킬 때 handler를 사용해 메인 스레드로 전달해 UI 업데이트를 시킬 수 있다

Thread{
            for(i in 30 downTo 0){
                runOnUiThread{
                    binding.timer.text = "$i"
                }
                Thread.sleep(1000)
            }
        }.start()

handler를 사용하지 않고 runOnUiThread를 사용하여 UI를 업데이트할 수도 있다.

Message

Handler를 통해 다른 스레드로 전달되는 작업 단위이다. Message 객체에는 핸들러가 처리해야 할 작업에 대한 정보가 포함되어 있다. 이 정보에는 Runnable 객체나 작업을 식별하는 정수 상수 등이 포함될 수 있다.

Looper

스레드의 메시지 큐를 루프로 실행하고, 큐에 있는 메시지들을 처리하는 역할을 한다.

기본적으로 안드로이드 앱은 스레드마다 한 개의 Looper가 존재하여 Looper는 스레드의 메시지 큐를 계속 확인하고 이를 처리한다.

Coroutine

코루틴이란 비동기 프로그래밍을 위한 방식으로 일반적인 스레드보다 가벼우면서도 비동기 작업을 효율적으로 처리할 수 있는 기능이다.

안드로이드 앱에서 비동기 작업은 필수적이다. 비동기 프로그래밍이란 요청과 그 결과가 동시에 일어나지 않을 거라는 약속이다. 서버에게 데이터를 요청한 후 요청에 따른 응답을 계속 기다리지 않고 다른 액션을 취하거나 서버에게 다른 요청사항을 보내는 것도 가능하다. 네트워크 요청, 파일 입출력, 데이터베이스 액세스등 시간이 오래 걸리는 작업을 처리할 때 코루틴을 사용하는게 효율적이다.

lifecycleScope.launch(Dispatchers.IO) {
	delay(3000)
	Log.d(TAG,"코루틴1 : ${Thread.currentThread().name}")
	withContext(Dispatchers.Main){
		Log.d(TAG,"코루틴2 : ${Thread.currentThread().name}")
	}
}
Log.d(TAG,"onCreate : ${Thread.currentThread().name}")

//logcat
onCreate : main
코루틴 1 : DefaultDispatcher-worker-3
코루틴 2 : main

scope : 코루틴 블락을 생성
Dispatcher : 어떤 thread에서 실행시킬지 정함(Default, Main, IO)
withContext : 실행환경을 바꾸고 싶을 때 (위의 예로는 IO에서 Main으로 실행환경을 바꿈)

profile
정진이

0개의 댓글