[안드로이드] Android에서 Thread는 ??
Thread는 무엇일까?
Thread는 프로세스 내에서 실행되는 하나의 작업 단위입니다.
Thread의 특징
- 공유 메모리 : 같은 프로세스 내에서 실행되는 여러 스레드는 각 스레드마다 독립적인 스택을 갖고있어 스레드 간에 데이터를 쉽게 주고 받을 수 있지만, 동시에 접근할 때는 동기화가 필요합니다.
- 독립적 실행 : 각 스레드는 독립적으로 실행되며, 자신의 실행 흐름을 갖고 있습니다.
- 경량 프로세스 : 스레드는 일반적인 프로세스보다 더 가벼운 단위입니다. 새로운 프로세스를 생성하는 것보다 자원이 적게 듭니다.
그렇다면, Android에서의 Thread는 ?
크게 Main(UI) Thread와 Background Thread로 나눌 수 있습니다.
Main Thread는 앱의 모든 UI 작업을 담당합니다. 사용자의 입력 이벤트 처리, 화면 업데이트, UI 요소 간의 상호작용 등이 모두 Main Thread에서 처리됩니다.
Main Thread에서는 무거운 작업을 수행하면 안됩니다. UI가 멈추거나 ANR(Application Not Responding) 오류가 발생할 수 있습니다.
import android.annotation.SuppressLint
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.TextView
class MainActivity : AppCompatActivity() {
@SuppressLint("MissingInflatedId")
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val textView = findViewById<TextView>(R.id.textView)
val button = findViewById<Button>(R.id.button)
button.setOnClickListener {
try {
Thread.sleep(10000)
} catch (e: InterruptedException) {
e.printStackTrace()
}
textView.text = "스레드 테스트"
}
}
}
이렇게 Main Thread에서 버튼이 클릭 될 때 Thread.sleep(10000)을 통해 현재 실행 중인 Main Thread를 10초 동안 다른 작업을 하지 못하도록 멈추게 해봤습니다.
로그에서
이렇게 경고를 하는 것을 볼 수 있습니다.
때문에 이를 방지하기 위해 Main Thread에서는 무거운 작업을 하면 안된다는 것을 알 수 있습니다 ~
자세한 설명은
위의 글에서 확인해주세요 !
그렇다면, 이를 방지하기 위해 무거운 작업을 수행하기 위해서는 Background Thread를 사용해야 합니다.
Background Thread는 Main Thread 외의 모든 스레드를 지칭하는 스레드입니다. 모든 비동기 작업을 여기서 처리합니다.
Background Thread 종류
1. Thread 클래스
val thread = Thread {
try {
Thread.sleep(1000)
} catch (e : InterruptedException) {
e.printStackTrace()
}
}
thread.start()
- 람다 블록을 통해 실행할 코드를 정의하고 Thread.sleep()을 통해 현재 실행 중인 스레드를 1초 동안 멈춥니다.
- InterruptedException : 다른 스레드가 현재 스레드를 깨울 때 발생할 수 있는 에러 처리
- start()를 통해 스레드가 시작됩니다.
2. Handler
Handler는 주로 Looper와 같이 쓰여 메세지나 작업을 안전하게 전달 할 수 있게 해줍니다.
* Looper : 특정 스레드가 무한 루프를 돌며 메시지 큐에서 메시지나 작업을 꺼내 처리할 수 있도록 합니다.
많이 사용하는 Looper의 메서드는 getMainLooper() 와 myLopper()가 있습니다.
getMainLooper() -> Main Thread에 바인딩 된 Looper 객체 반환하며, 백그라운드 스레드에서 UI 스레드로 작업을 전송할 때 사용합니다.
myLopper() -> 현재 실행 중인 스레드에 바인딩 된 Looper 객체를 반환하며, 현재 스레드가 가지고 있는 Looper를 필요할 때 사용됩니다.
val getMainHandler = Handler(Looper.getMainLooper())
getMainHandler.postDelayed({
}, 1000)
val myHandler = Handler(Looper.myLooper()!!)
myHandler.postDelayed({
}, 1000)
3. AsyncTask
- AsyncTask는 백그라운드에서 작업을 수행하고, 결과를 UI 스레드로 전달하기 위해 사용했지만, deprecated 되었습니다.
4. Coroutine
- Kotlin에서 제공하는 경량 스레드로, 비동기 작업을 쉽게 처리할 수 있게 해줍니다.
GlobalScope.launch(Dispatchers.IO) {
withContext(Dispatchers.Main) {
}
}
- Dispatchers.IO를 통해 백그라운드 스레드에서 실행되도록 설정하고, 작업이 완료된 뒤, Dispatchers.Main을 통해 코루틴을 Main Thread로 전환하여 UI를 업데이트합니다.
결론
Android는 Main Thread와 Background Thread를 나누어 앱의 성능을 최적화하고 사용자 경험을 향상시키기 때문에, 상황에 맞는 Thread 처리를 해야 합니다 !
코루틴은 내용이 많아 다음에 길게 정리해보도록 하겠습니다.
감사합니다 ^-^