Android – 쓰레드 만들기 with. 코틀린

프로그래밍을 하다 보면 쓰레드가 필요한 경우가 많습니다.

쓰레드는 ‘프로세스에서 할당된 일’이라고 생각하면 됩니다.
쓰레드를 만드는 이유는 여러 일을 동시에 처리하고 싶기 때문입니다.

예를 들어 오른쪽 화면에는 스톱워치가 계속 돌아가고, 왼쪽 화면에는 타이머가 계속 돌아가게 만들고 싶습니다.
이 때 쓰레드를 만들지 않으면, CPU는 위의 두 가지 일을 한 가지 일로 생각해서 순차적으로 처리합니다.
즉 스톱워치가 모두 돌아간 다음 타이머가 돌아갑니다.

하지만 ‘스톱워치 일’, ‘타이머 일’을 각각 만들고 CPU에게 넘겨주면 CPU는 여러 일을 빠르게 처리하기 위해서 두 일을 번갈아서 처리하게 되고 이 과정이 마치 동시에 처리되는 것처럼 보이게 됩니다! 이렇게 두 일을 번갈아 처리하는 방식을 Concourrency 방식이라고 합니다.

만약 CPU의 코어가 여러 개라면 각 코어마다 쓰레드를 맡아서 처리할 수도 있습니다. 이 방식을 Paralleism 방식이라고 하며 정말로 동시에 여러 일을 처리하게 됩니다.

요즘에는 멀티 코어를 지원하는 CPU가 많기 때문에 Parallelism 방식을 사용한다고 생각하면 됩니다.
쓰레드 만들기는 쉽게 말해 ‘할 일을 다른 코어로 보내기’ 입니다!

이제 코틀린으로 쓰레드를 만들어 봅시다!

package com.example.myapplication

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.SystemClock
import android.util.Log

class MainActivity : AppCompatActivity() {
    private var isRunning=true

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val thread=ThreadClass()
        thread.start()
    }

    inner class ThreadClass:Thread(){
        override fun run(){
            while(isRunning){
                SystemClock.sleep(100)
                Log.d("쓰레드",System.currentTimeMillis().toString())
            }
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        isRunning=false
    }
}

onCreate메소드부터 살펴 봅시다.

thread상수는 ThreadClass를 가리키는 참조상수입니다. ThreadClass를 인스턴스화한 뒤 start메소드를 호출하면
ThreadClass라는 새로운 쓰레드를 생성하고 다른 코어에서 실행하는 것입니다.

onCreate밖에 정의된 ThreadClass를 살펴 봅시다.

Thread()클래스를 상속받아서 쓰레드를 만듭니다. 동작할 소스는 run메소드를 오버라이딩해서 작성하면 됩니다.
필자는 Log.d메소드를 이용해서 로그캣에 현재 앱 사용 시간을 출력하였습니다. isRunning=true이니 0.1초 간격으로 사용 시간이 계속 출력됩니다.

이런 식으로 로그캣에는 계속 데이터가 찍히고, 이와 별개로 우리는 앱을 사용하는데 지장이 없습니다.

onDestroy메소드를 살펴 봅시다.

onDestroy는 앱이 종료되면 호출되는 메소드입니다. 앱은 기본적으로 (메인 쓰레드)에서 계속 실행됩니다. 이 메소드는 원래 (메인 쓰레드)를 중지시키는 역할을 합니다.

하지만 쓰레드 객체를 만들고 start하고부터 (다른 쓰레드)가 실행됩니다.
즉 onDestroy를 해도 (다른 쓰레드)가 실행되는 것은 중지되지 않습니다.
그래서 필드 isRunning에 false를 저장해서 (다른 쓰레드)에 동작하는 반복문을 강제 중지시켰습니다.

이러한 방식으로 프로그램을 안전하게 종료시킬 수 있습니다.

다른 쓰레드에서 UI 접근하는 방법!!

안드로이드에서 UI는 메인 쓰레드에서만 접근할 수 있습니다. 다른 쓰레드에서는 전혀 접근할 수 없습니다.

하지만 runOnUiThread메소드를 통해 메인 쓰레드의 UI를 접근할 수 있습니다.

그 사용 방법은 아래 코드와 같습니다.

    inner class ThreadClass:Thread(){
        override fun run(){
            while(isRunning){
                SystemClock.sleep(100)
                runOnUiThread{
                        textview.text=System.currentTimeMillis().toString()
                }
            }
        }
    }

0.1초마다 한 번씩 runOnUiThread메소드를 호출합니다. 이 메소드 인수에는 접근할 UI에 관련된 클래스가 들어갑니다. 필자는 (텍스트뷰의 텍스트가 변하는 클래스)를 작성하였습니다.

SAM변환을 하지 않고 인수에 객체를 넘겨줄 때, 해당 객체는 Runnable클래스를 상속받아야 하고 run메소드를 오버라이딩해서 UI내용을 작성해야 합니다.

    inner class ThreadClass:Thread(){
        override fun run(){
            while(isRunning){
                SystemClock.sleep(100)
                runOnUiThread(UIClass())
            }
        }
    }

    inner class UIClass:Runnable{
        override fun run(){
            textview.text=System.currentTimeMillis().toString()
        }
    }

위,아래 텍스트뷰의 내용이 다른 것은 runOnUiThread가 계속 호출된 결과입니다.

Leave a Reply

Your email address will not be published. Required fields are marked *