Kotlin

[Kotlin] 스레드(Thread)의 개념 및 runOnUiTread 사용 방법

cob 2022. 11. 16. 13:21

 

Thread

 

Thread는 메인 스레드와 백그라운드 스레드로 나누어진다.
UI 변경은 메인 스레드(UI 변경 스레드)에서만 가능하고, 백그라운드 스레드는 네트워크 작업, 데이터베이스 작업, 계산량이 많은 작업을 한다.

 

 

메인 스레드(UI 스레드) 란?
 앱이 처음 시작되면 시스템이 스레드 하나를 생성하는데 이를 메인 스레드라고 한다.
메인 스레드의 역할은 크게 두 가지로 액티비티의 모든 명 주기 관련 콜백을 실행을 담당하거나,
버튼, 에디트텍스트와 같은 UI 위젯을 사용한 용자의 이벤트와 UI드로잉 이벤트를 담당한다.
그렇기 때문에 UI 스레드라과 불린다.
백그라운드 스레드 란?
 작업량이 큰 연산이나, 네트워크 통신, 데이터베이스 쿼리 등은 처리에 긴 시간이 걸린다. 이 모든 작업을 메인 스레드의 큐에 넣고 작업하면 한 작업의 처리가 완료될 때까지 다른 작업을 처리하지 못하는 현상이 발생한다.
이러한 현상을 피하기 위해 백그라운드 스레드를 이용하여 처리한다

 

 


1.  메인 스레드 runOnUiThread() 구조

public final void runOnUiTread(Runnable action) {
	if(Tread.currentTread() != mUiThread){ // 메인 스레드가 아니면 액션을 메인 스레드에 전달
		mHadler.post(action);
	} else {  // 메인 스레드이면 스레드 생성
		action.run()
	}
 }
  • runOnUiTread() 메서드에서는 UI스레드가 아니면 핸들러를 이용해 UI 스레드의 이벤트 큐에 action을 전달하고,
    만약 UI 스레드이면 action.run()을 수행
    즉, 어떤 스레드에 있든지 runOnUiTread() 메서드는 UI 스레드에서 Runnable객체를 실행한다.

 

 

 


2. 메인 스레드 runOnUiThread() 메서드 사용 방법 

UI 자원에 Main Thread와 Sub Thread가 동시 접근하여 동기화 이슈를 발생시키는 것을 방지하기 위해 UI 자원 사용은 UI Thread에서만 가능하도록 만들었다. UI Thread를 사용하기 위한 방법이 runOnUiThread()이다.

 

2-1) 기본 사용 방법

//UI 스레드 생성
runOnUiTread {
	// 변경하고 싶은 로직 
}
  • 백그라운 스레드 → UI 스레드 → UI 자원

 

2-2)  백그라운드에서 runOnUiThread()  활용 예

백그라운드에서 UI자원을 사용하려면 메인 스레드에 UI 자원 사용 메시지를 전달해야 한다.

( Timer() 안에서 사용 )

private fun start(){
        btn_start.text = "일시정지"
        btn_start.setBackgroundColor(getColor(R.color.red))
        isRunning = true

        // 스톱워치를 시작하는 로직
        timer = timer(period = 10) {
            /*
                timer() 코틀린에서 제공하는 함수로 일정한 주기를 방복하는 동작을 수행
                timer()의 {} 안에 쓰인 코드들은 백그라운드 스레드에서 실행
            */
            time++ // 10밀리초 단위 타이머

            // 시간 계산
            val milli_second = time % 100
            val second = (time % 6000) / 100
            val minute = time / 6000

            // 뷰의 접근은  뷰를 생성한 메인 스레드에서만 할 수 있다
            runOnUiThread{          // UI 스레드 생성(메인 스레드)
                if(isRunning) {     // UI 업데이트 조건 설정
                    // 밀리초
                    tv_millisecond.text =
                        if(milli_second < 10) ".0${milli_second}" else ".${milli_second}"
                    // 초
                    tv_second.text = if(second < 10) ".0${second}" else ".${second}"
                    // 분
                    tv_minute.text = "${minute}"
                }
            }
        }
  }
  • 뷰에 접근하기 위해서는 메인 스레드(UI 스레드)인 runOnUiThread()를 사용해야 한다.

 

( 백그라운드 스레드 안에서 사용)

Thread(Runnable {
    while (cnt3 < 100) {
        Log.d("Thread-3", "${cnt3++}")
        Thread.sleep(2000)

        runOnUiThread {
            if (cnt3 % 2 == 0) {
                back.setBackgroundColor(R.color.white)
            } else {
                back.setBackgroundColor(R.color.black)
            }
        }
    }
}).start()

 

반응형