-
[Android/Java] 스레드(Thread)와 핸들러(Handler)Android/Java 2022. 3. 18. 13:09반응형
[모든 포스팅은 개인적 공부를 위해 작성된 글입니다]
<스레드(Thread)란?>
- 동시 수행이 가능한 작업 단위
- 현재 수행 중인 작업 외의 기능을 동시에 처리할 때 사용
- ex) 네트워킹 수행 시
- 네트워킹의 경우 대기 시간이 길어지므로 처리와 동시에 UI도 멈춤 상태로 있게 되는 문제 발생
- 이전에는 스레드 사용을 권장사항으로 여겼지만, 현재 버전에서는 반드시 사용해야 하는 것으로 변경되었음(사용하지 않는 경우 네트워킹 기능 자체가 동작하지 않음)
<멀티 스레드 방식>
- 하나의 프로세스 안에서 여러 개의 작업이 동시 수행됨
- 같은 프로세스 안에서 메모리 리소스 공유하여 효율적인 처리 가능
- 단, 동시에 리소스에 접근 시 데드락(DeadLock) 발생할 수 있음
*데드락(DeadLock) - 여러 개의 스레드가 동시에 공통으로 사용하는 메모리 리소스에 접근했을 때 어떤 것을 먼저 처리할지 판단할 수 없어 발생하는 문제*
<메인 스레드(Main Thread)>
- 다른 말로 UI(User Interface) Thread 라고도 함
- 사용자의 input을 받는 스레드
- 절대 정지시킬 수 없음
- 정지 || 종료 시키면 더이상 사용자의 input을 받을 수 없으므로
- 정지시키면 앱이 종료됨
- 안드로이드에서 UI를 처리할 때 사용되는 기본 스레드
- 메인 스레드에서 이미 UI에 접근하고 있으므로 새로 생성한 다른 스레드에서는 핸들러(Handler) 객체를 사용해서 메인 스레드로 메시지를 전달함으로써 메인 스레드에서 처리하도록 만들 수 있음
*핸들러(Handler) - 데드락 문제 해결을 위해 각 스레드 안에서 작업을 순서대로 처리하도록 함*
*UI 변경은 반드시 메인 스레드에서만 이루어져야 함*
- 안드로이드에는 크게 두 종류의 스레드가 있는데 Main Thread(UI Thread)와 Worker Thread가 있음
- Main Thread
- 어플리케이션을 실행하면 기본적으로 실행되는 스레드
- UI 업데이트 담당
- 시간이 오래 걸리는 작업을 하기에는 부적합(ex 네트워크, DB 작업)
- 시간이 오래 걸리는 작업을 수행하면 그 작업이 완료되기 전까지는 UI가 멈춰 있을 것이므로 사용자에게 좋지 않은 사용 경험을 주게 됨(다른 작업들이 같은 자원을 붙잡고 있으면 ANR(Application Not Responding) 발생 가능성도 있음)
- Worker Thread
- 특정 목적을 위해 따로 생성하여 사용하는 스레드(ex 네트워크, DB 작업)
<스레드 생성 방법>
- 방법 1.
new Thread(new Runnable() { @Override public void run() { //수행할 작업 } }).start();
- 스레드 이름을 따로 지정하지 않고 생성
- 스레드가 할 일을 Runnable에 지정
- 방법 2.
class insert_thread extends Thread{ @Override public void run() { super.run(); } }
insert_thread thread = new insert_thread(); thread.start();
<Looper>
- 하나의 스레드는 하나의 Looper 가짐
- 하나의 Looper는 하나의 스레드 담당
- 어플리케이션이 실행되면(MainActivity가 실행되면) 자동으로 메인 스레드에 존재하는 Looper 돌기 시작
- 내부에 Message Queue 존재
- 무한 루프를 돌면서 Meesage Queue에 있는 메시지를 하나씩 Handler에 전달
<메시지(Message)>
- 메시지 객체에 Runnable 객체 또는 Message 객체가 존재
- Lopper로 메시지 전달하는 경우
- 메시지 객체에 Message 객체 존재하는 경우 sendMessage() 통해 전달
- 메시지 객체에 Runnable 객체 존재하는 경우 post 통해 전달
- Looper로부터 메시지 받는 경우
- 메시지 객체에 Message 객체 존재하는 경우 handleMessage() 통해 메시지 받고 작업 수행
- 메시지 객체에 Runnable 객체 존재하는 경우 해당 Runnable 객체의 run() 호출하여 수행
<핸들러와 Looper 사용법>
- 방법 1(deprecated 됨).
- deprecated 된 이유
- Handler가 담당할 Looper 지정하지 않아(Handler가 암시적으로 Looper 선택) 특정 작업 손실, 충돌 등의 문제가 발생할 수 있음
new Thread(new Runnable() { @Override public void run() { Looper.prepare(); //Handler 생성 Looper.loop(); } }).start();
- Looper.prepare()
- 해당 스레드에 종속되는 Looper, MessageQueue 준비하고 Handler 생성
- Handler 생성과 동시에 Looper와 Handler가 연결됨
- 스레드의 run() 메서드 마지막에서 Looper.loop() 호출하여 Message 기다림
- 방법 2.
- Looper 명시
new Thread(new Runnable() { @Override public void run() { new Handler(Looper.getMainLooper()).post(new Runnable() { @Override public void run() { } }); } }).start();
- Looper.getMainLooper()를 통해 메인 스레드의 Looper 사용할 것이라고 명시
- Looper를 사용하였으므로 UI 변경 가능
반응형'Android > Java' 카테고리의 다른 글
[Android/Java] 액티비티 생명주기 (0) 2022.05.16 [Android/Java] 프래그먼트(Fragment) (0) 2022.04.03 [Android/Java] 다이얼로그(Dialog)+커스텀 다이얼로그(Custom Dialog) (0) 2022.03.12 [Android/Java] SharedPreferences(간단한 데이터 저장) (0) 2022.02.27 [Android/Java] 스피너(Spinner) (0) 2022.01.22