안드로이드 멀티스레딩 입문...

49
안드로이드 멀티스레딩 입문 이 저작물에는 크리에이티브 커먼즈 저작자표시-비영리-변경금지 4.0 국제 라이선스가 적용 되어 있습니다. 이 라이선스의 설명을 보고 싶으시면 http://creativecommons.org/licenses/by-nc-nd/4.0/ 을(를) 참조하세요.

Transcript of 안드로이드 멀티스레딩 입문...

Page 1: 안드로이드 멀티스레딩 입문 송형주

안드로이드 멀티스레딩 입문송 형 주

이 저작물에는 크리에이티브 커먼즈 저작자표시-비영리-변경금지 4.0 국제 라이선스가 적용 되어 있습니다. 이 라이선스의 설명을 보고 싶으시면 http://creativecommons.org/licenses/by-nc-nd/4.0/ 을(를) 참조하세요.

Page 2: 안드로이드 멀티스레딩 입문 송형주

발표자 소개

• 근무 경력 !

• 삼성전자 DMC 연구소/SW센터 근무 (`06~`13)!

• SKT 종합기술원 근무 (현재)!

• 시스템 소프트웨어, 모바일/웹 플랫폼 관련 개발 업무 수행

Page 3: 안드로이드 멀티스레딩 입문 송형주

책을 쓰기도 했습니다.

Page 4: 안드로이드 멀티스레딩 입문 송형주

안드로이드 + 멀티스레딩!!

이걸 1시간에 다 설명?

Page 5: 안드로이드 멀티스레딩 입문 송형주

왜 멀티스레딩을 사용하는가?

Page 6: 안드로이드 멀티스레딩 입문 송형주

main 스레드

main 스레드

파일A 다운로드

파일B 다운로드

파일C 다운로드

A 스레드

B 스레드

C 스레드

파일A 다운로드 파일B 다운로드 파일C 다운로드

병행 실행 (Concurrent)순차 실행 (Sequential)

싱글 스레드 멀티 스레드

Page 7: 안드로이드 멀티스레딩 입문 송형주

멀티 스레딩의 장점

• 태스크 들의 병행 실행을 통한 최적화!

• CPU 활용의 극대화 (특히, 멀티코어)!

• UI 반응성을 높여줌

Page 8: 안드로이드 멀티스레딩 입문 송형주

멀티 스레딩은!성능 최적화의 훌륭한 수단이지만,!잘못쓰면 오히려 독이 된다.

Page 9: 안드로이드 멀티스레딩 입문 송형주

• 불규칙한 스레드 실행 순서 : 구현 & 디버깅이 어렵다.!

• 가장 큰 이유는 Race Condition !!

멀티 스레딩은 왜 어렵나?

Page 10: 안드로이드 멀티스레딩 입문 송형주

간단한 멀티 스레드 예제

main()

스레드 실행 코드

Page 11: 안드로이드 멀티스레딩 입문 송형주

Foo 스레드

Bar 스레드

출력 장치

실행 결과

불규칙한 스레드 실행 순서멀티 스레딩이 왜 어려운가?

출력 출력

Page 12: 안드로이드 멀티스레딩 입문 송형주

Race Condition (경쟁 상태)“두개 이상의 스레드가 !

공유 데이터에 동시에 접근할 때,!!

각 스레드가!어떤 순서로 공유 데이터에 접근하는지에 따라 !

실행 결과가 매번 달라지는 상황”

(ex.객체)

멀티 스레딩이 왜 어려운가?

Page 13: 안드로이드 멀티스레딩 입문 송형주

Race Condition 예제

스레드 실행 코드

main()공유 객체

Page 14: 안드로이드 멀티스레딩 입문 송형주

Race Condition

Foo 스레드

Bar 스레드

sharedObj 객체

add()

num

10번 호출10번 호출

실행 결과

멀티 스레딩이 왜 어려운가?

당연히 최종 결과는 num이 20이 나와야 한다.

1씩 증가

Page 15: 안드로이드 멀티스레딩 입문 송형주

10메모리!(num)

CPU!(스레드) 10 10+1=11

1.read

2. increment

3.write

11

• 1. 메모리에서 num의 현재 값을 CPU로 읽어온다. (메모리 read)!

• 2. CPU는 읽어온 값에 1을 더한다. (연산)!

• 3. CPU는 새로 변경된 값을 메모리 num에 Write 한다. (메모리 write)

Time

왜 결과가 틀리게 나오는가?

num++ 의 동작 원리에 대해서 살펴보자

Page 16: 안드로이드 멀티스레딩 입문 송형주

add() 메서드 정상 동작 케이스

10

메모리!(num)

11 11+1=121.read

2. increment

3.write

11

Time

스레드 1

스레드 2

10 10+1=11

2. increment

1.read 3.write

11 12

add()호출 add() 리턴

add() 리턴add()호출

Page 17: 안드로이드 멀티스레딩 입문 송형주

add() 메서드 에러 케이스

10메모리!(num)

10

read

increment

write

스레드 1

스레드 2

10 10+1=11

read write

11

10+1=11

11

11

increment

스레드는 언제든 컨텍스트 스위칭 될 수 있다.

Time

add()호출 add() 리턴

add() 리턴add() 호출

Page 18: 안드로이드 멀티스레딩 입문 송형주

• 단순한 해결책 - 싱글 스레드만을 사용한다.!

• 일반적인 해결책 - 동기화 (Locking 기법)!

• 한번에 하나의 스레드만이 해당 코드를 수행 할 수 있게끔 보장해주는 기법!

• synchronized 키워드!

• java.util.concurrent 패키지

Race Condition 해결책

Page 19: 안드로이드 멀티스레딩 입문 송형주

동기화 적용

Foo 스레드

Bar 스레드

sharedObj 객체

add()

num

10번 호출10번 호출

1씩 증가

Lock을 차지한 스레드만이 add() 메서드 호출이 가능 (Lock이 없는 스레드는 add() 메서드 처리가 끝날 때까지 대기한다.)

synchronized 적용

Page 20: 안드로이드 멀티스레딩 입문 송형주

Thread Safety (스레드 안전성)

“클래스에 여러 스레드가 동시에 접근할 때,!

스레드의 실행 순서에 관계없이 항상 동일한 결과가 나오면

해당 클래스는 스레드 안전하다고 할 수 있다”

ex. ArrayList 클래스는 thread-safe 하지 않다.

Page 21: 안드로이드 멀티스레딩 입문 송형주

ArrayList 예제

main()

스레드 실행 코드

Page 22: 안드로이드 멀티스레딩 입문 송형주

ArrayList 예제 결과

ArrayList

Bar 스레드

Foo 스레드

1~10까지 추가1~10까지 추가

예상 결과 실제 결과1 실제 결과2

Page 23: 안드로이드 멀티스레딩 입문 송형주

ArrayList의 API 문서를 보면,!

ArrayList is not thread safe“Note that this implementation is not synchronized. If multiple threads access an ArrayList instance concurrently, and at least one of the threads modifies the list structurally, it must be synchronized externally.”

http://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html

이 클래스의 구현은 동기화 처리를 하지 않는다.!!

여러 스레드가 ArrayList 인스턴스에 동시에 접근하고, !적어도 스레드 하나가 리스트의 내용을 수정하는 상황이라면, !

반드시 외부에서 동기화 처리를 해야한다.

Page 24: 안드로이드 멀티스레딩 입문 송형주

CopyOnWriteArrayList를 써보자

“A thread-safe variant of ArrayList”http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/CopyOnWriteArrayList.html

Page 25: 안드로이드 멀티스레딩 입문 송형주

CopyOnWriteArrayList 예제

Page 26: 안드로이드 멀티스레딩 입문 송형주

정리해보면,

• 멀티 스레딩의 장점!

• Race Condition (경쟁 상태)!

• Synchronization (동기화)!

• Thread Safe (스레드 안전성)

Page 27: 안드로이드 멀티스레딩 입문 송형주

왜 안드로이드에서는!멀티 스레딩을 고려해야 하는가

Page 28: 안드로이드 멀티스레딩 입문 송형주

안드로이드 App을 실행해보면…

Page 29: 안드로이드 멀티스레딩 입문 송형주

안드로이드 App 스레드 구조

UI 스레드

Binder_1 스레드

Binder_2 스레드

Activity 객체

Binder 스레드는!IPC 용도로 사용됨!(ex. intent 수신,!

Framework 와의 통신 등)

우리가 작성한 Activity는!UI 스레드 기반으로 !동작한다.

안드로이드 프로세스

Binder 통신

Page 30: 안드로이드 멀티스레딩 입문 송형주

UI Thread• 안드로이드 애플리케이션의 Main Thread!

• 애플리케이션이 실행됐을때, 시스템에 의해 생성된다.!

• 역할!

• UI 이벤트 (사용자 입력 / 화면 Drawing) 처리!

• 안드로이드 컴포넌트(Activity, Service 등)의 인스턴스 생성 및 생명 주기 콜백 호출

http://developer.android.com/guide/components/processes-and-threads.html

Page 31: 안드로이드 멀티스레딩 입문 송형주

UI 이벤트 처리 - 싱글 스레드 모델

UI 스레드

버튼 클릭

문자 입력

스크롤

생명 주기

안드로이드 프레임워크 Activity View

이벤트 전달

이벤트 enqueue

이벤트 dequeue

이벤트 처리

UI 스레드는 무한루프를 돌면서!이벤트 메시지큐를 폴링함

Message Queue

안드로이드 애플리케이션

UI 스레드의 역할

Page 32: 안드로이드 멀티스레딩 입문 송형주

UI 스레드 - 순차적인 이벤트 처리

UI!스레드

Button1 !

Message Queue

안드로이드 애플리케이션

버튼1 클릭버튼2 클릭

Button2 !

클릭 이벤트 핸들러 클릭 이벤트 핸들러

①,③

② Button1 이벤트 !핸들러 실행

④ Button2 이벤트 핸들러 실행

이벤트!dequeue

Button1의 클릭 이벤트 핸들러가 늦게 처리된다면??

Page 33: 안드로이드 멀티스레딩 입문 송형주

코드로 살펴보면..

button1 이벤트 핸들러 (Long Task 처리)

button2 이벤트 핸들러

Long-Task : 긴 작업 흉내내기 위해 Sleep 사용!

이 코드는 UI 스레드가 실행 결국, UI 스레드가 Block 되버림

Page 34: 안드로이드 멀티스레딩 입문 송형주
Page 35: 안드로이드 멀티스레딩 입문 송형주

Long Task의 예• 네트워크 통신 (ex. 소켓 통신, HTTP 처리 등)!

• 파일 읽고 쓰기!

• 데이터 베이스에서 데이터 생성/수정/삭제!

• 이미지 프로세싱!

• 텍스트 파싱

주로 I/O (네트워크, 파일, DB) 관련 작업과 CPU Intensive한 작업이 Background 태스크의 예이다.

UI 스레드에서 실행하면 안될 것

Page 36: 안드로이드 멀티스레딩 입문 송형주

Application Not RespondingUI 스레드가 입력 이벤트(터치, 키입력 등)를 5초내에 처리하지 않으면 발생

http://developer.android.com/training/articles/perf-anr.html

Page 37: 안드로이드 멀티스레딩 입문 송형주

어떻게 개선을 할까?

UI!스레드

Button1 !

Message Queue

안드로이드 애플리케이션

버튼1 클릭버튼2 클릭

Button2 !

클릭 이벤트 핸들러 클릭 이벤트 핸들러

①,④

② Button1 이벤트 !핸들러 실행

⑤ Button2 이벤트 핸들러 실행

이벤트!dequeue

작업!스레드

Long Task

③ Long Task를 !별도 스레드로 수행

멀티 스레딩을 활용해보자

Page 38: 안드로이드 멀티스레딩 입문 송형주

코드로 살펴보면,

button1 이벤트 핸들러 !(작업 스레드가 Long Task 처리)

Long-Task 작업!

여기서 작업 스레드가 멈춰있음 (Blocked)

Page 39: 안드로이드 멀티스레딩 입문 송형주
Page 40: 안드로이드 멀티스레딩 입문 송형주

UI!스레드

Button1 !

Message Queue

안드로이드 애플리케이션

버튼1 클릭

TextView1 !

클릭 이벤트 핸들러

② Button1 이벤트 !핸들러 실행

이벤트!dequeue

작업!스레드

Long Task

③ Long Task를 !별도 스레드로 수행

“Long Task Finished”

④ UI 업데이트를 통해,!Long Task 종료 알림

Long Task가 끝난 것을 어떻게 알릴까?UI를 업데이트하자.

Page 41: 안드로이드 멀티스레딩 입문 송형주

코드를 살펴보면,

작업 스레드가 Long Task 처리를 끝내면,!TextView에 “Long Task is Finished” 문자열 표시

Page 42: 안드로이드 멀티스레딩 입문 송형주

결과는 !CalledFromWrongThreadException !!

View Hierarchy를 생성한 메서드만(UI 스레드)이 view에 접근할 수 있다.

Page 43: 안드로이드 멀티스레딩 입문 송형주

Why !CalledFromWrongThreadException ?

• Android UI Toolkit은 Thread Safe가 아님.!

• 그래서, 오직 UI 스레드 하나만 UI Toolkit에 접근 허용

Page 44: 안드로이드 멀티스레딩 입문 송형주

참고: Android UI toolkitandroid.widget과 android.view 패키지에 포함된 UI 컴포넌트

(http://developer.android.com/guide/components/processes-and-threads.html 참조)

• View - 화면상의 사각 영역에 그림을 그리고, 사용자의 입력을 처리하는 객체!• widget - View를 상속해서 UI 구성하는 컴포넌트로서 Button, Textview 등이 해당

Page 45: 안드로이드 멀티스레딩 입문 송형주

①,⑤

⑥ UI 스레드가!TextView 업데이트 수행

어떻게 해결?

UI!스레드

Button1 !

Message Queue

안드로이드 애플리케이션

버튼1 클릭

TextView1 !

클릭 이벤트 핸들러

② Button1 이벤트 !핸들러 실행

이벤트!dequeue

작업!스레드

Long Task

③ Long Task를 !별도 스레드로 수행

“Long Task Finished”

④ UI 업데이트 요청 이벤트 메시지 전달

UI 업데이트 처리를 UI 스레드에 요청

Page 46: 안드로이드 멀티스레딩 입문 송형주

UI 스레드에 메시지를 보내려면?View.post() 메서드

Activity.runOnUiThread() 메서드

Page 47: 안드로이드 멀티스레딩 입문 송형주

코드를 살펴보면,

작업 스레드에서 textView의 UI 수정(에러 발생)

post() 메서드를 통해,!TextView 업데이트를 UI 스레드에 요청

기존 코드

수정 코드 View.post() 활용

Page 48: 안드로이드 멀티스레딩 입문 송형주
Page 49: 안드로이드 멀티스레딩 입문 송형주

정리하면,

• UI 스레드는 블록되면 안된다. (UI 반응성을 높이기 위해)!

• Long-Task 처리는 작업 스레드를 통해 실행!

• 작업 스레드에서 View나 Widget의 UI 업데이트 처리를 하면 안된다.!

• UI 업데이트는 UI 스레드를 통해 실행