JiYoung Dev πŸ–₯

[Android] μŠ€λ ˆλ“œ(Thread) & ν•Έλ“€λŸ¬(Handler) (2023.07.27) λ³Έλ¬Έ

full stack/μ•ˆλ“œλ‘œμ΄λ“œ

[Android] μŠ€λ ˆλ“œ(Thread) & ν•Έλ“€λŸ¬(Handler) (2023.07.27)

Shinjio 2023. 7. 27. 17:26

Thread

 

 

큐에 μŠ€λ ˆλ“œ μ €μž₯ 

컴퓨터 μž‘μ—…μ€ CPUκ°€ 함. CPUλŠ” ν•œλ²ˆμ— ν•˜λ‚˜μ˜ 일처리λ₯Ό 함

μž‘μ—… μŠ€μΌ€μ₯΄λ§μ„ 톡해 λ©€ν‹° μŠ€λ ˆλ“œλ₯Ό κ°€λŠ₯ν•˜κ²Œ 함 → μ‹œλΆ„ν•  μ‹œμŠ€ν…œ

 

 

μŠ€λ ˆλ“œ 라이프사이클 (μŠ€λ ˆλ“œ 생λͺ…μ£ΌκΈ°)

  • 첫번째 μŠ€λ ˆλ“œλŠ” λ‘λ²ˆμ§Έ μŠ€λ ˆλ“œμ—κ²Œ 양보 : yeild
  • λ‘λ²ˆμ§Έ μŠ€λ ˆλ“œλŠ” 첫번째 μŠ€λ ˆλ“œμ˜ cpuλŠ” κ°€λ‘œμ±” : interupt
  • start(), run(), yeild(), interupt(), sleep() λ“±μ˜ λ©”μ„œλ“œλ‘œ κ΅¬ν˜„μ΄ λ˜μ–΄ 있음 
  • μŠ€λ ˆλ“œ1 μ‹œμž‘ ν›„ λ‹€μ‹œ 싀행될 λ•ŒλŠ” run() μƒνƒœλ‘œ 싀행됨(λ‹€μ‹œ start() X) 

 

 

https://link2me.tistory.com/1730

 

 

Handler 

 

μ•ˆλ“œλ‘œμ΄λ“œμ—μ„œ μ“°λ ˆλ“œλ₯Ό μ‚¬μš©ν•˜κΈ° μœ„ν•΄μ„œλŠ” Handlerκ°€ ν•„μš”ν•¨

μ•ˆλ“œλ‘œμ΄λ“œ μ–΄ν”Œμ„ μ‹€ν–‰μ‹œν‚€λ©΄ Taskκ°€ μƒμ„±λ˜κ³  κ·Έ μ•ˆμ— activity듀이 μŒ“μ΄λŠ” ꡬ쑰 

μ•ˆλ“œλ‘œμ΄λ“œλŠ” μ–΄ν”Œμ„ μ—¬λŸ¬κ°œ μ‹€ν–‰μ‹œν‚¬ 수 있음 → ν•˜λ‚˜μ˜ μ–΄ν”Œλ¦¬μΌ€μ΄μ…˜μ„ Thread둜 λ§Œλ“€μ–΄λ‘μ—ˆμŒ 

 

 

 

 

 

μŠ€λ ˆλ“œλŠ” 동기화가 ν•„μš”ν•˜λ‹€ 

 

MainThread : UIμž‘μ—…, Click 등을 진행 

μ•ˆλ“œλ‘œμ΄λ“œ μžμ²΄μ—μ„œ UI ν˜Όμ„ μ΄ 생길 것을 μ˜ˆλ°©ν•˜κΈ° μœ„ν•΄ SubTreadμ—μ„œ UI에 μ†λŒˆ 수 없도둝 λ§Œλ“€μ–΄ λ‘μ—ˆμŒ

 

 

 

μ΄λŸ¬ν•œ 이유둜 쀑간에 Handlerλ₯Ό λ°°μΉ˜ν•¨

Handler에 μž‘μ—… μš”μ²­ → λ©”μ‹œμ§€ 전솑 

HandlerλŠ” MainThread의 μž‘μ—…Queue에 μ ‘κ·Όν•˜μ—¬ μž‘μ—…μ„ 진행

 

 

 

 

 


 

 

μŠ€λ ˆλ“œ & ν•Έλ“€λŸ¬ κ΅¬ν˜„

 

package com.sjy.ex20230727

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.widget.Button
import android.widget.TextView

class MainActivity : AppCompatActivity() {

    lateinit var btnStart1 : Button
    lateinit var tvStart1 : TextView

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

        // ThreadλŠ” class둜 μ„€κ³„ν•œλ‹€!
        // classλ₯Ό μ‹€ν–‰ν•˜λ €λ©΄ 객체 μƒμ„±ν•˜κ³  μ‹€ν–‰ν•΄μ•Ό 함

        btnStart1 = findViewById(R.id.btnStart1)
        tvStart1 = findViewById(R.id.tvStart1)

        btnStart1.setOnClickListener {
            var th1 : cntThread = cntThread()
            //Threadλ₯Ό μ‹€ν–‰ν•˜λ €λ©΄ 객체λ₯Ό 생성해야 함
            th1.start() //μ€€λΉ„, μ‹€ν–‰ 전에 μ€€λΉ„λΆ€ν„° 해야함. start λ‚΄λΆ€μ—μ„œ μžλ™μœΌλ‘œ 싀행됨
            //μœ„ μƒνƒœκΉŒμ§€λ§Œ ν•˜λ©΄ νŠ•κΉ€ -> μ•ˆλ“œλ‘œμ΄λ“œμ΄κΈ° λ•Œλ¬Έμ— ν•œκ°€μ§€ μž‘μ—…μ„ 더 ν•΄μ•Ό 함
            //-> Handler μ‚¬μš©
        }
    }

    var cntHandler : Handler = object: Handler(Looper.getMainLooper()){
        //object : λ°”λ‘œ 객체화
        //Handler cntHandler = new Handler(Looper.getManinLooper())
        override fun handleMessage(msg: Message) {
            super.handleMessage(msg)
            //메세지λ₯Ό λ°›μ•„μ„œ μ²˜λ¦¬ν•˜λŠ” κ³³
            tvStart1.text = msg.arg1.toString()
        }
    }

    inner class cntThread : Thread(){
        //클래슀 μ•ˆμ— ν΄λž˜μ„œ μƒμ„±μ‹œ ν‚€μ›ŒνŠΈ : inner
        //Thread ν΄λž˜μŠ€λŠ” Thread()λ₯Ό μƒμ†λ°›μŒ

        //run() λ©”μ„œλ“œλ₯Ό μ˜€λ²„λΌμ΄λ”©
        //1. Thread 클래슀 상속 (extends)
        //2. Runnable μΈν„°νŽ˜μ΄μŠ€ κ΅¬ν˜„ (implements)
        //단좕킀 : alt+insert
        override fun run() {
//            super.run()
            //super.λ©”μ†Œλ“œ 이름
            //=> μ‚­μ œν•΄λ„ λ˜λŠ” 경우 : λ§€κ°œλ³€μˆ˜κ°€ 없을 λ•Œ
            //=> μ‚­μ œν•˜λ©΄ μ•ˆλ˜λŠ” 경우 : λ§€κ°œλ³€μˆ˜κ°€ μžˆμ„ λ•Œ

            //10~1κΉŒμ§€ μ„ΈκΈ°
            for(i in 10 downTo  1){
                //1. 메세지 생성
                var msg : Message = Message()
                //2. 데이터 μ„ΈνŒ… - 3κ°œκΉŒμ§€λ§Œ κ°€λŠ₯(arg1 : Int, arg2 : Int, obj : object)
                //=> 데이터가 λ§Žμ„ λ•Œ VOλ₯Ό μ„€κ³„ν•˜μ—¬ obj에 λ‹΄μ•„μ„œ 보낼 수 있음
                msg.arg1 = i
                //3. Handler에 전솑
                cntHandler.sendMessage(msg)
                Thread.sleep(500)
            }
            //μœ„μ˜ μž‘μ—…μ΄ λλ‚˜λ©΄ destroyed됨 (계속 μ‹€ν–‰μƒνƒœκ°€ μ•„λ‹˜)
            //즉, ThreadλŠ” runλ©”μ„œλ“œκ°€ μ’…λ£Œλ˜λ©΄ μ†Œλ©Έλ¨
        }
    }
}

 

 

* start1 λ²„νŠΌμ„ 2번 클릭 

→ Thread 2개 생성 

 

 

좔상화 

 

package com.sjy.ex20230727

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.os.Message
import android.widget.Button
import android.widget.TextView
import org.w3c.dom.Text

class MainActivity : AppCompatActivity() {

    lateinit var btnStart1 : Button
    lateinit var tvStart1 : TextView
    lateinit var btnStart2 : Button
    lateinit var tvStart2 : TextView

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

        // ThreadλŠ” class둜 μ„€κ³„ν•œλ‹€!
        // classλ₯Ό μ‹€ν–‰ν•˜λ €λ©΄ 객체 μƒμ„±ν•˜κ³  μ‹€ν–‰ν•΄μ•Ό 함

        btnStart1 = findViewById(R.id.btnStart1)
        tvStart1 = findViewById(R.id.tvStart1)
        btnStart2 = findViewById(R.id.btnStart2)
        tvStart2 = findViewById(R.id.tvStart2)

        btnStart1.setOnClickListener {
            var th1 : cntThread = cntThread(tvStart1)
            //Threadλ₯Ό μ‹€ν–‰ν•˜λ €λ©΄ 객체λ₯Ό 생성해야 함
            th1.start() //μ€€λΉ„, μ‹€ν–‰ 전에 μ€€λΉ„λΆ€ν„° 해야함. start λ‚΄λΆ€μ—μ„œ μžλ™μœΌλ‘œ 싀행됨
            //μœ„ μƒνƒœκΉŒμ§€λ§Œ ν•˜λ©΄ νŠ•κΉ€ -> μ•ˆλ“œλ‘œμ΄λ“œμ΄κΈ° λ•Œλ¬Έμ— ν•œκ°€μ§€ μž‘μ—…μ„ 더 ν•΄μ•Ό 함
            //-> Handler μ‚¬μš©
        }

        btnStart2.setOnClickListener {
            var th1 : cntThread = cntThread(tvStart2)
            th1.start()
        }


    }

    var cntHandler : Handler = object: Handler(Looper.getMainLooper()){
        //object : λ°”λ‘œ 객체화
        //Handler cntHandler = new Handler(Looper.getManinLooper())
        override fun handleMessage(msg: Message) {
            super.handleMessage(msg)
            //메세지λ₯Ό λ°›μ•„μ„œ μ²˜λ¦¬ν•˜λŠ” κ³³
            var tv : TextView = msg.obj as TextView
            //as : ν˜•λ³€ν™˜
            tv.text = msg.arg1.toString()
//            tvStart1.text = msg.arg1.toString()
        }
    }

    inner class cntThread(var tv : TextView) : Thread(){
        //클래슀 μ•ˆμ— ν΄λž˜μ„œ μƒμ„±μ‹œ ν‚€μ›ŒνŠΈ : inner
        //Thread ν΄λž˜μŠ€λŠ” Thread()λ₯Ό μƒμ†λ°›μŒ

        //run() λ©”μ„œλ“œλ₯Ό μ˜€λ²„λΌμ΄λ”©
        //1. Thread 클래슀 상속 (extends)
        //2. Runnable μΈν„°νŽ˜μ΄μŠ€ κ΅¬ν˜„ (implements)
        //단좕킀 : alt+insert
        override fun run() {
//            super.run()
            //super.λ©”μ†Œλ“œ 이름
            //=> μ‚­μ œν•΄λ„ λ˜λŠ” 경우 : λ§€κ°œλ³€μˆ˜κ°€ 없을 λ•Œ
            //=> μ‚­μ œν•˜λ©΄ μ•ˆλ˜λŠ” 경우 : λ§€κ°œλ³€μˆ˜κ°€ μžˆμ„ λ•Œ

            //10~1κΉŒμ§€ μ„ΈκΈ°
            for(i in 10 downTo  1){
                //1. 메세지 생성
                var msg : Message = Message()
                //2. 데이터 μ„ΈνŒ… - 3κ°œκΉŒμ§€λ§Œ κ°€λŠ₯(arg1 : Int, arg2 : Int, obj : object)
                //=> 데이터가 λ§Žμ„ λ•Œ VOλ₯Ό μ„€κ³„ν•˜μ—¬ obj에 λ‹΄μ•„μ„œ 보낼 수 있음
                msg.arg1 = i
                msg.obj = tv
                //3. Handler에 전솑
                cntHandler.sendMessage(msg)
                Thread.sleep(500)
            }
            //μœ„μ˜ μž‘μ—…μ΄ λλ‚˜λ©΄ destroyed됨 (계속 μ‹€ν–‰μƒνƒœκ°€ μ•„λ‹˜)
            //즉, ThreadλŠ” runλ©”μ„œλ“œκ°€ μ’…λ£Œλ˜λ©΄ μ†Œλ©Έλ¨
        }
    }
}