1. 안드로이드 멀티스레딩 입문
송 형 주
이 저작물에는 크리에이티브 커먼즈 저작자표시-비영리-변경금지 4.0 국제 라이선스가 적용 되어 있습니다.
이 라이선스의 설명을 보고 싶으시면 http://creativecommons.org/licenses/by-nc-nd/4.0/ 을(를) 참조하세요.
2. 발표자 소개
• 근무 경력 !
• 삼성전자 DMC 연구소/SW센터 근무 (`06~`13)!
• SKT 종합기술원 근무 (현재)!
• 시스템 소프트웨어, 모바일/웹 플랫폼 관련 개발 업무 수행
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++ 의 동작 원리에 대해서 살펴보자
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() 호출
18. • 단순한 해결책 - 싱글 스레드만을 사용한다.!
• 일반적인 해결책 - 동기화 (Locking 기법)!
• 한번에 하나의 스레드만이 해당 코드를 수행 할 수 있게끔
보장해주는 기법!
• synchronized 키워드!
• java.util.concurrent 패키지
Race Condition 해결책
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 인스턴스에 동시에 접근하고, !
적어도 스레드 하나가 리스트의 내용을 수정하는 상황이라면, !
반드시 외부에서 동기화 처리를 해야한다.
29. 안드로이드 App 스레드 구조
UI
스레드
Binder_1
스레드
Binder_2
스레드
Activity 객체
Binder 스레드는!
IPC 용도로 사용됨!
(ex. intent 수신,!
Framework 와의 통신 등)
우리가 작성한 Activity는!
UI 스레드 기반으로 !
동작한다.
안드로이드 프로세스
Binder 통신
30. UI Thread
• 안드로이드 애플리케이션의 Main Thread!
• 애플리케이션이 실행됐을때, 시스템에 의해 생성된다.!
• 역할!
• UI 이벤트 (사용자 입력 / 화면 Drawing) 처리!
• 안드로이드 컴포넌트(Activity, Service 등)의 인스턴스 생성
및 생명 주기 콜백 호출
http://developer.android.com/guide/components/processes-and-threads.html
31. UI 이벤트 처리 - 싱글 스레드 모델
UI
스레드
버튼 클릭
문자 입력
스크롤
생명 주기
안드로이드 프레임워크
Activity View
이벤트
전달
이벤트
enqueue
이벤트
dequeue
이벤트 처리
①
②
③
④
UI 스레드는 무한루프를 돌면서!
이벤트 메시지큐를 폴링함
Message Queue
안드로이드 애플리케이션
UI 스레드의 역할
32. UI 스레드 - 순차적인 이벤트 처리
UI!
스레드
Button1
!
Message Queue
안드로이드 애플리케이션
버튼1 클릭버튼2 클릭
Button2
!
클릭 이벤트 핸들러 클릭 이벤트 핸들러
①,③
② Button1 이벤트 !
핸들러 실행
④ Button2 이벤트
핸들러 실행
이벤트!
dequeue
Button1의 클릭 이벤트 핸들러가 늦게 처리된다면??
33. 코드로 살펴보면..
button1 이벤트 핸들러 (Long Task 처리)
button2 이벤트 핸들러
Long-Task : 긴 작업 흉내내기 위해 Sleep 사용!
이 코드는 UI 스레드가 실행
결국, UI 스레드가 Block 되버림
34.
35. Long Task의 예
• 네트워크 통신 (ex. 소켓 통신, HTTP 처리 등)!
• 파일 읽고 쓰기!
• 데이터 베이스에서 데이터 생성/수정/삭제!
• 이미지 프로세싱!
• 텍스트 파싱
주로 I/O (네트워크, 파일, DB) 관련 작업과 CPU Intensive한 작업이
Background 태스크의 예이다.
UI 스레드에서 실행하면 안될 것
36. Application Not Responding
UI 스레드가 입력 이벤트(터치, 키입력 등)를 5초내에 처리하지 않으면 발생
http://developer.android.com/training/articles/perf-anr.html
37. 어떻게 개선을 할까?
UI!
스레드
Button1
!
Message Queue
안드로이드 애플리케이션
버튼1 클릭버튼2 클릭
Button2
!
클릭 이벤트 핸들러 클릭 이벤트 핸들러
①,④
② Button1 이벤트 !
핸들러 실행
⑤ Button2 이벤트
핸들러 실행
이벤트!
dequeue
작업!
스레드
Long
Task
③ Long Task를 !
별도 스레드로 수행
멀티 스레딩을 활용해보자
38. 코드로 살펴보면,
button1 이벤트 핸들러 !
(작업 스레드가 Long Task 처리)
Long-Task 작업!
여기서 작업 스레드가
멈춰있음 (Blocked)
39.
40. UI!
스레드
Button1
!
Message Queue
안드로이드 애플리케이션
버튼1 클릭
TextView1
!
클릭 이벤트 핸들러
①
② Button1 이벤트 !
핸들러 실행
이벤트!
dequeue
작업!
스레드
Long
Task
③ Long Task를 !
별도 스레드로 수행
“Long Task Finished”
④ UI 업데이트를 통해,!
Long Task 종료 알림
Long Task가 끝난 것을 어떻게 알릴까?
UI를 업데이트하자.
41. 코드를 살펴보면,
작업 스레드가 Long Task 처리를 끝내면,!
TextView에 “Long Task is Finished” 문자열 표시
44. 참고: Android UI toolkit
android.widget과 android.view 패키지에 포함된 UI 컴포넌트
(http://developer.android.com/guide/components/processes-and-threads.html 참조)
• View - 화면상의 사각 영역에 그림을 그리고, 사용자의 입력을 처리하는 객체!
• widget - View를 상속해서 UI 구성하는 컴포넌트로서 Button, Textview 등이 해당
45. ①,⑤
⑥ UI 스레드가!
TextView 업데이트 수행
어떻게 해결?
UI!
스레드
Button1
!
Message Queue
안드로이드 애플리케이션
버튼1 클릭
TextView1
!
클릭 이벤트 핸들러
② Button1 이벤트 !
핸들러 실행
이벤트!
dequeue
작업!
스레드
Long
Task
③ Long Task를 !
별도 스레드로 수행
“Long Task Finished”
④ UI 업데이트 요청 이벤트
메시지 전달
UI 업데이트 처리를 UI 스레드에 요청
46. UI 스레드에 메시지를 보내려면?
View.post() 메서드
Activity.runOnUiThread() 메서드
47. 코드를 살펴보면,
작업 스레드에서 textView의 UI 수정
(에러 발생)
post() 메서드를 통해,!
TextView 업데이트를 UI 스레드에 요청
기존 코드
수정 코드
View.post() 활용
48.
49. 정리하면,
• UI 스레드는 블록되면 안된다. (UI 반응성을 높이기 위해)!
• Long-Task 처리는 작업 스레드를 통해 실행!
• 작업 스레드에서 View나 Widget의 UI 업데이트 처리를
하면 안된다.!
• UI 업데이트는 UI 스레드를 통해 실행