본문 바로가기
Android/Android Studio

[안드로이드/Kotlin] Thread개념 및 예제

by YOONAYEON 2022. 5. 19.
프로그램 → 프로세스 → 스레드

 

 

Program (프로그램)

 

- 파일이 저장 장치에 저장되어 있지만, 메모리에는 올라가 있지 않은 정적인 상태

- os가 프로그램에게 독립적인 메모리 공간을 할당하지 않아 실행되고 있지 않은 상태

- 그냥 실행 파일/코드라고 생각해도 될듯

 

 

Process (프로세스)

 

- 운영체제로부터 자원을 할당받은 작업의 단위

- 실행되고 있는 컴퓨터 프로그램 

- 실행 파일이 컴퓨터 메모리에 올라가있는 상태

 

 

Thread (스레드)

 

- 하나의 실행 흐름

- 프로세스와는 다른 더 작은 실행 단위의 개념

 

 : Single 스레드

 

 

 

 

: Multi 스레드

(하나의 프로세스가 여러 작업을 여러 스레드를 사용하여 동시에 처리.

  각 task간 스위칭을 매우 빠르게)

 

 

 

❓프로세스와 스레드의 차이점

: os는 프로세스마다 각각의 독립된 메모리 영역(코드,데이터,스택, 힙의 형식)에 할당해주기 때문에 프로세스는 다른 프로세스의 변수나 자료에 접근하지 못하지만, 스레드는 같은 프로세스 내의 일부 메모리 영역을 함께 공유한다. 

 

 

Thread in Android Studio

 

1. MainThread : 안드로이드 os에서 자동으로 만들어주는 스레드 (View Control가능)

2. Worker Thread : 그외 스레드. 네트워킹 등 시간이 많이 걸리는 작업들 처리 (View Control 불가)

 

 

# 스레드 사용 예제

 

class MainActivity: AppCompatActivity(){
	override fun onCreate(){
    	super.onCreate(saved)
        setContentView(R.layout.activity_main)
        
        val a = A()
        val b = B()
        
        //a.join()으로 하면, A스레드 끝난 후에 B스레드 실행
        a.start()	//스레드 시작
        b.start()
    }
    
    class A: Thread(){
    	override fun run(){		//스레드 시작과 동시에 run함수가 실행
            super.run()
            for(i in 1..1000)
            	Log.d("test", "Thread1: $i")
        }
    }
    
    class B: Thread(){
    	override fun run(){
            super.run()
            for(i in downTo 1)
            	Log.d("test", "Thread2: $i")
        }
    }
    
}

 

→ 무작위 순서로 스레드가 실행됨을 알 수 있다.

→ 스레드 간 순서를 임의로 정하려면 join이나 AsyncTask사용

 

 

뷰 렌더링

 

- 뷰를 재갱신 하는 것

- 멀티스레드 작업 시, 뷰렌더링은 메인스레드에서만 작업이 가능

 

 

# 워커스레드에서 MainActivity의 이미지뷰 바꾸기 예제 

 

class MainActivity: AppCompatActivity(){

    lateinit var binding: ActivityMainBinding
    
    override fun onCreate(saved: Bundle){
    	super.onCreate(saved)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)
        
        //다른 스레드에서 전달한 메시지를 꺼내서 전달해주는 역할
        //메인 스레드의 고유한 Looper를 가져와서 핸들러에 전달
        val handler = Handler(Looper.getMainLooper)
        
        //이미지 임의 추가
        val imgList = arrayListOf<Int>()
        imgList.add(R.drawable.~)
        
        // 1) 핸들러 사용 (스레드간 통신을 도와주는 클래스)
        Thread{
        	for(img in imgList){
            	//이 부분의 코드가 메인스레드로 전달되어 뷰렌더링 작업이 메인에서 이루어짐
            	handler.post{
                    binding.iv.setImageResource(img)
                    Thread.sleep(2000)
                }
            }
        }.start()
        
        
        // 2) 상속받은 액티비티에서 제공해주는 함수 이용
        Thread{
        	for(img in imgList){
            	//runOnUiThread함수 사용 시 내부코드는 메인스레드에서 실행됨
            	runOnUiThread{ 
                	binding.iv.setImageResource(img)
                }
                Thread.sleep(2000)
            }
        }.start()
        
    }
}