1page.title=프로세스 및 스레드
2page.tags=수명 주기, 배경
3
4@jd:body
5
6<div id="qv-wrapper">
7<div id="qv">
8
9<h2>이 문서의 내용</h2>
10<ol>
11<li><a href="#Processes">프로세스</a>
12  <ol>
13    <li><a href="#Lifecycle">프로세스 수명 주기</a></li>
14  </ol>
15</li>
16<li><a href="#Threads">스레드</a>
17  <ol>
18    <li><a href="#WorkerThreads">작업자 스레드</a></li>
19    <li><a href="#ThreadSafe">스레드로부터 안전한 메서드</a></li>
20  </ol>
21</li>
22<li><a href="#IPC">프로세스 간 통신</a></li>
23</ol>
24
25</div>
26</div>
27
28<p>애플리케이션 구성 요소가 시작되고 애플리케이션에 실행 중인 다른 구성 요소가 없으면
29Android 시스템은 하나의 실행 스레드로 애플리케이션의 Linux 프로세스를
30시작합니다. 기본적으로 같은 애플리케이션의 모든 구성 요소는 같은 프로세스와 스레드에서 실행됩니다
31("기본" 스레드라고 합니다). 애플리케이션 구성 요소가 시작되고 (애플리케이션의 다른 구성 요소가 존재해서)
32해당 애플리케이션의 프로세스가 이미 존재하면 해당 구성 요소는
33프로세스 내에서 시작되고 같은 실행 스레드를 사용합니다. 하지만 애플리케이션 내의
34여러 가지 구성 요소가 각자 별도의 프로세스에서 실행되도록 할 수도 있고, 어느 프로세스에든 추가 스레드를
35만들 수 있습니다.</p>
36
37<p>이 문서는 프로세스와 스레드가 Android 애플리케이션에서 작동하는 방식을 설명합니다.</p>
38
39
40<h2 id="Processes">프로세스</h2>
41
42<p>기본적으로 같은 애플리케이션의 모든 구성 요소는 같은 프로세스와 스레드에서 실행되고,
43대부분의 애플리케이션은 이를 바꿔서는 안 됩니다. 그러나 어느 프로세스가 특정 구성 요소에 속하는지
44확인해야 할 경우 매니페스트 파일에서 확인할 수 있습니다.</p>
45
46<p>구성 요소 &mdash;<a href="{@docRoot}guide/topics/manifest/activity-element.html">{@code
47&lt;activity&gt;}</a>와 <a href="{@docRoot}guide/topics/manifest/service-element.html">{@code
48&lt;service&gt;}</a>, <a href="{@docRoot}guide/topics/manifest/receiver-element.html">{@code
49&lt;receiver&gt;}</a> 및 <a href="{@docRoot}guide/topics/manifest/provider-element.html">{@code
50&lt;provider&gt;}</a>&mdash;의 각 유형에 대한 매니페스트 항목은 구성 요소를 실행할 프로세스를 지정하는 {@code android:process} 속성을 지원합니다.
51 이러한 속성을 설정하여 각 구성 요소를 자체 프로세스에서 실행시키거나
52다른 구성 요소를 제외한 일부 구성 요소만 프로세스를 공유하게 할 수 있습니다  또한,
53{@code android:process}를 설정하여 다른 애플리케이션의 구성 요소를 같은 프로세스에서 실행시킬 수 있습니다.
54단, 이는 애플리케이션이 같은 Linux 사용자 ID를 공유하고 같은 인증서에
55서명되었을 경우에 한합니다.</p>
56
57<p><a href="{@docRoot}guide/topics/manifest/application-element.html">{@code
58&lt;application&gt;}</a> 요소도 {@code android:process} 속성을 지원하여,
59모든 구성 요소에 적용되는 기본값을 설정합니다.</p>
60
61<p>Android는 어느 시점엔가 프로세스를 종료하기로 결정할 수도 있습니다. 즉 메모리가 부족하거나, 사용자에게 더욱 즉각적인 서비스를 제공하는
62다른 프로세스가 이 프로세스의 중단을 필요로 하는 경우 등입니다. 그러면 중단된
63프로세스에서 실행되고 있던 애플리케이션 구성 요소도 따라서 소멸됩니다.  그와 같은 구성 요소가 할 작업이 다시 생기면
64그에 대한 프로세스도 다시 시작됩니다.</p>
65
66<p>어느 프로세스를 삭제할지 결정할 때, Android 시스템은
67사용자에 대한 이들의 상대적 중요성을 가늠합니다.  예를 들어, 눈에 보이는 액티비티를 호스팅하는 프로세스와 비교하여
68화면에 보이지 않는 액티비티를 호스팅하는 프로세스를 쉽게 종료할 수 있습니다. 프로세스 종료 결정은
69해당 프로세스에서 실행되는 구성 요소의 상태에 따라 달라집니다. 종료할
70프로세스를 결정하는 데 사용하는 규칙은 아래에 설명되어 있습니다. </p>
71
72
73<h3 id="Lifecycle">프로세스 수명 주기</h3>
74
75<p>Android 시스템은 최대한 오래 애플리케이션 프로세스를 유지하려고 시도하지만,
76결국 오래된 프로세스를 제거하고 새 프로세스나 더 중요한 프로세스에 사용할 메모리를 확보해야 합니다.  유지할
77프로세스와 종료할 프로세스를 결정하기 위해
78시스템은 프로세스에서 실행되는 구성 요소와 해당 구성 요소의 상태에 기초하여 각 프로세스에
79"중요 계층"을 부여합니다.  중요도가 낮은
80프로세스가 먼저 제거되고, 그 다음으로 중요도가 낮은 프로세스를 제거하는 식으로
81필요에 따라 시스템 리소스를 회복하는 것입니다.</p>
82
83<p>중요 계층에는 다섯 가지 단계가 있습니다. 다음 목록은
84중요도 순서에 따른 프로세스 유형을 나타낸 것입니다(첫 번째 프로세스가 <em>가장 중요하고</em>
85<em>마지막으로 종료됩니다)</em>.</p>
86
87<ol>
88  <li><b>전경 프로세스</b>
89    <p>사용자가 현재 진행하는 작업에 필요한 프로세스입니다.  다음 조건 중
90하나가 참일 경우 프로세스가 전경에 있는 것으로 간주합니다.</p>
91
92      <ul>
93        <li>사용자와 상호 작용하는 {@link android.app.Activity}를 호스팅할 경우({@link
94android.app.Activity}의 {@link android.app.Activity#onResume onResume()} 메서드가 호출되었을 경우
95).</li>
96
97        <li>사용자와 상호 작용하는 액티비티에 바인딩된 {@link android.app.Service}를 호스팅할 경우.
98</li>
99
100        <li>"전경에서" 실행되는 {@link android.app.Service}를 호스팅할 경우(
101해당 서비스가 {@link android.app.Service#startForeground startForeground()}를 호출했을 경우).
102
103        <li>수명 주기 콜백 중 하나를 실행하는 {@link android.app.Service}를 호스팅할 경우
104({@link android.app.Service#onCreate onCreate()}, {@link android.app.Service#onStart
105onStart()} 또는 {@link android.app.Service#onDestroy onDestroy()}).</li>
106
107        <li>{@link
108android.content.BroadcastReceiver#onReceive onReceive()} 메서드를 실행하는 {@link android.content.BroadcastReceiver}를 호스팅할 경우.</li>
109    </ul>
110
111    <p>일반적으로, 주어진 시간에 존재하는 전경 프로세스는 몇 개밖에 되지 않습니다.  이들은 최후의
112수단으로서만 종료됩니다. 즉, 메모리가 너무 부족해 계속 실행할 수 없는 경우를 말합니다.  일반적으로 그 시점이 되면
113기기가 메모리 페이징 상태에 도달한 것이므로 전경 프로세스 몇 개를 중단해야만
114사용자 인터페이스의 반응성을 유지할 수 있습니다.</p></li>
115
116  <li><b>가시적 프로세스</b>
117    <p>전경 구성 요소는 없지만
118사용자가 화면에서 보는 것에 영향을 미칠 수 있는 프로세스입니다. 다음 조건 중 하나가 참이면
119가시적 프로세스로 간주합니다.</p>
120
121      <ul>
122        <li>전경에 있지는 않지만 사용자에게 보이는 {@link android.app.Activity}를 호스팅할 경우
123({@link android.app.Activity#onPause onPause()} 메서드가 호출되었을 경우).
124예를 들어 이것은 전경 액티비티가 대화를 시작하여 이전 액티비티가 그 뒤에 보일 경우
125 발생합니다.</li>
126
127        <li>눈에 보이는(또는 전경) 액티비티에 바인딩된 {@link android.app.Service}를 호스팅할 경우.
128</li>
129      </ul>
130
131      <p>가시적인 프로세스는 매우 중요도가 높은 것으로 취급하고 모든 전경 프로세스를 실행하는 데 필요할 경우에만
132종료됩니다. </p>
133    </li>
134
135  <li><b>서비스 프로세스</b>
136    <p>{@link
137android.content.Context#startService startService()} 메서드로 시작되었지만 두 개의 상위 계층 분류에
138들어가지 않는 서비스를 실행하는 프로세스입니다. 서비스 프로세스는 사용자가 보는 것과 직접 연결되어 있지는 않지만,
139일반적으로 사용자가 신경 쓰는 작업을 하므로(배경에서 음악 재생 또는 네트워크에서 데이터 다운로드)
140시스템은 모든 전경 및 가시적 프로세스와 함께 실행할 만큼 메모리가 충분하지 않을 경우에만
141프로세스를 중단합니다. </p>
142  </li>
143
144  <li><b>배경 프로세스</b>
145    <p>현재 사용자에게 보이지 않는 액티비티를 보유한 프로세스입니다(액티비티의
146{@link android.app.Activity#onStop onStop()} 메서드가 호출되었습니다). 이와 같은 프로세스는
147사용자 환경에 직접적 영향을 미치지 않고, 시스템은 언제든 이 프로세스를 중단시켜
148전경,
149가시적 또는 서비스 프로세스를 위한 메모리를 확보할 수 있습니다. 보통 한번에 실행 중인 배경 프로세스가 많은 편이므로 이들은
150LRU(최저 사용 빈도) 목록에 보관하여 사용자가 가장 최근에 본 액티비티가 있는
151프로세스가 가장 마지막에 중단되도록 합니다. 액티비티가 수명 주기 메서드를 올바르게 구현하고
152자신의 현재 상태를 저장할 경우, 사용자가 액티비티로 다시 이동할 때 액티비티가 모든 가시적 상태를
153복원하므로 프로세스를 중단시키더라도 사용자 환경에는 눈에 띄게 영향을 미치지
154않습니다. 상태 저장과 복원에 관한 정보는 <a href="{@docRoot}guide/components/activities.html#SavingActivityState">액티비티</a>
155문서를 참조하십시오.</p>
156  </li>
157
158  <li><b>빈 프로세스</b>
159    <p>활성 애플리케이션 구성 요소를 보유하지 않은 프로세스입니다.  이런 프로세스를
160유지하는 유일한 이유는 다음에 내부 구성 요소를 실행할 때 시작 시간을 절약하기 위한 캐싱
161때문입니다.  시스템은 프로세스 캐시와 기본 커널 캐시 사이에서 전반적인 시스템 리소스의 균형을 맞추기 위해
162이 프로세스를 중단시키는 경우가 많습니다.</p>
163  </li>
164</ol>
165
166
167  <p>Android는 프로세스에서 현재 활성 상태인 구성 요소의 중요도에 따라
168프로세스에 가장 높은 수준을 부여합니다.  예를 들어, 프로세스가 서비스와 가시적 액티비티를 호스팅할 경우,
169해당 프로세스는 서비스 프로세스가 아니라 가시적 프로세스 등급이 부여됩니다.</p>
170
171  <p>또한, 프로세스의 등급은 다른 프로세스가 이에 의존할 경우 상승할 수 있습니다.
172즉, 다른 프로세스에 서비스를 제공하는 프로세스가 서비스 제공 대상 프로세스보다
173등급이 낮은 경우는 있을 수 없습니다. 예를 들어 프로세스 A의 콘텐츠 제공자가 프로세스 B의 클라이언트에 서비스를 제공하거나
174프로세스 A의 서비스가 프로세스 B의 구성 요소에 바인딩되어 있을 경우 프로세스 A는 항상 중요도가
175프로세스 B와 같거나 그보다 높습니다.</p>
176
177  <p>서비스를 실행하는 프로세스가 배경 액티비티가 포함된 프로세스보다 높으므로,
178장기 작업을 시작하는 액티비티는 작업자 스레드만 생성하기보다는 해당 작업에 대한 <a href="{@docRoot}guide/components/services.html">서비스</a>를 시작하는 것이 좋습니다.
179이는 특히 작업이 해당 액티비티보다 오래 지속될 경우 더욱 중요합니다.
180예를 들어, 웹사이트에 사진을 업로드하는 액티비티가 업로드를 수행하는 서비스를 시작해야
181사용자가 액티비티를 떠나더라도 배경에서 업로드를 지속할 수 있습니다.
182서비스를 사용하면 액티비티에 어떤 일이 발생하든 해당 작업에 반드시
183"서비스 프로세스" 우선 순위 이상이 부여됩니다. 이것이 브로드캐스트 수신기가 시간이 오래 걸리는 작업을
184스레드에 넣기보다는 서비스를 사용해야 하는 것과 같은 이유입니다.</p>
185
186
187
188
189<h2 id="Threads">스레드</h2>
190
191<p> 애플리케이션이 시작되면 시스템이 애플리케이션에 대한 실행의 스레드를 생성하며, 이를
192"기본"이라고 합니다. 이 스레드는 드로어블 이벤트를 포함하여 적절한 사용자 인터페이스 위젯에
193이벤트를 발송하는 역할을 맡기 때문에 중요합니다. 이것은 Android UI 도구 키트의 구성 요소({@link
194android.widget}과 {@link android.view} 패키지의 구성 요소)와 개발자의 애플리케이션이
195상호 작용하는 스레드이기도 합니다. 따라서 기본 스레드는
196UI 스레드라고 불릴 때도 있습니다.</p>
197
198<p>시스템은 구성 요소의 각 인스턴스에 대해 별도의 스레드를 생성하지 <em>않습니다</em>. 같은
199프로세스에서 실행되는 모든 구성 요소는 UI 스레드에서 시작되고, 각 구성 요소를 호출하는 시스템이
200해당 스레드에서 발송됩니다. 따라서
201시스템 콜백에 응답하는 메서드(사용자 작업을 보고하는 {@link android.view.View#onKeyDown onKeyDown()} 또는
202수명 주기 콜백 메서드)는 항상 프로세스의 UI 스레드에서 실행됩니다.</p>
203
204<p>예를 들어, 사용자가 화면의 버튼을 터치하면, 앱 UI 스레드가 위젯에 터치 이벤트를 발송하고,
205위젯은 눌린 상태를 설정하고 이벤트 대기열에
206무효화 요청을 게시합니다. UI 스레드가 이 요청을 대기열에서 해제하고 위젯에 스스로를 다시
207그려야 한다고 알립니다.</p>
208
209<p>앱이 사용자 상호작용에 응답하여 집약적인 작업을 수행할 때는 이 단일 스레드 모델은
210애플리케이션을 제대로 구현하지 않으면 낮은 성능을 보일 수 있습니다. 특히,
211모든 것이 UI 스레드에서 발생하고 네트워크 액세스나 데이터 베이스 쿼리 등의 긴 작업을 수행하면
212UI가 통째로 차단됩니다. 스레드가 차단되면 드로잉 이벤트를 포함하여
213모든 이벤트가 발송되지 않습니다. 사용자가 보기에는 애플리케이션이
214중단된 것처럼 보입니다. 더 나쁜 경우, UI 스레드가 몇 초 이상 차단되어 있으면
215(현재 약 5초) 사용자에게 악명 높은 "<a href="http://developer.android.com/guide/practices/responsiveness.html">애플리케이션이 응답하지
216않습니다</a>"(ANR) 대화가 표시됩니다. 그러면 사용자가 여러분의 애플리케이션을 종료 할 수도 있고, 불만족한 경우 앱을
217제거할 수도 있습니다.</p>
218
219<p>또한, Andoid UI 도구 키트는 스레드로부터 안전하지 <em>않습니다</em>. 따라서 UI를
220작업자 스레드에서 조작해서는 안 됩니다. 사용자 인터페이스 조작 작업은 모두 UI
221스레드에서 해야만 합니다. 결론적으로, Android의 단일 스레드 모델에는 두 가지 단순한 규칙이 있습니다.</p>
222
223<ol>
224<li>UI 스레드를 차단하지 마십시오.
225<li>Ui 스레드 외부에서 Android UI 도구 키트에 액세스하지 마십시오.
226</ol>
227
228<h3 id="WorkerThreads">작업자 스레드</h3>
229
230<p>위에 설명한 단일 스레드 모델로 인해, 애플리케이션 UI의 반응성을 위해서는
231UI 스레드를 차단하지 않는 것이 매우 중요합니다. 수행해야 할 작업이 있는데
232이들이 즉각적인 조치를 요하지 않는 경우, 이런 작업은 반드시 별도의 스레드에서 수행해야 합니다("배경" 또는
233"작업자" 스레드).</p>
234
235<p>예를 들어, 아래는 별도의 스레드에서 이미지를 다운로드하고 이를
236{@link android.widget.ImageView}에 표시하는 클릭 수신기에 대한 몇 가지 코드입니다.</p>
237
238<pre>
239public void onClick(View v) {
240    new Thread(new Runnable() {
241        public void run() {
242            Bitmap b = loadImageFromNetwork("http://example.com/image.png");
243            mImageView.setImageBitmap(b);
244        }
245    }).start();
246}
247</pre>
248
249<p>처음에는 네트워크 작업을 처리하기 위한 새 스레드를 생성하므로
250아무 문제 없이 작동하는 것처럼 보입니다. 하지만, 이것은 단일 스레드된 모델의 두 번째 규칙 즉, '<em>UI 스레드 외부에서
251Android UI 도구 키트에 액세스하지 마세요.</em>'를 위반합니다. 이 샘플은 UI 스레드 대신 작업자 스레드에서 {@link
252android.widget.ImageView}를 수정합니다. 이렇게 되면
253정의되지 않고 예기치 못한 동작이 발생하는 결과를 초래할 수 있고, 이는 추적하기 어려워 시간도 오래 걸립니다.</p>
254
255<p>이 문제를 해결하기 위해 Android는 다른 스레드에서 UI 스레드에 액세스하는 여러 가지 방식을
256제안합니다. 다음은 몇 가지 유용한 메서드 목록입니다.</p>
257
258<ul>
259<li>{@link android.app.Activity#runOnUiThread(java.lang.Runnable)
260Activity.runOnUiThread(Runnable)}</li>
261<li>{@link android.view.View#post(java.lang.Runnable) View.post(Runnable)}</li>
262<li>{@link android.view.View#postDelayed(java.lang.Runnable, long) View.postDelayed(Runnable,
263long)}</li>
264</ul>
265
266<p>예를 들어 위의 코드를 수정하려면 {@link
267android.view.View#post(java.lang.Runnable) View.post(Runnable)} 메서드를 사용하면 됩니다.</p>
268
269<pre>
270public void onClick(View v) {
271    new Thread(new Runnable() {
272        public void run() {
273            final Bitmap bitmap = loadImageFromNetwork("http://example.com/image.png");
274            mImageView.post(new Runnable() {
275                public void run() {
276                    mImageView.setImageBitmap(bitmap);
277                }
278            });
279        }
280    }).start();
281}
282</pre>
283
284<p>이 구현은 이제 스레드로부터 안전합니다. 네트워크 작업은 별도의 스레드에서 수행된 반면
285{@link android.widget.ImageView}는 UI 스레드에서 조작되었기 때문입니다.</p>
286
287<p>그러나, 작업이 복잡해질수록 이런 종류의 코드가 더 복잡해질 수 있고 유지 관리하기
288까다로워질 수 있습니다. 더 복잡한 상호 작용을 작업자 스레드로 처리하려면, 작업자 스레드에서
289{@link android.os.Handler}를 사용하여 UI 스레드에서 전달 받은 메시지를 처리하는 방안을
290고려해보십시오. 하지만 최선의 해결책은 {@link android.os.AsyncTask} 클래스를 확장하는 방법일 것입니다.
291이것은 UI와 상호 작용해야 하는 작업자 스레드 작업의 실행을 단순화합니다.</p>
292
293
294<h4 id="AsyncTask">AsyncTask 사용</h4>
295
296<p>{@link android.os.AsyncTask}를 사용하면 사용자 인터페이스에서 비동기식 작업을 수행할 수
297있게 해줍니다. 이것은 작업자 스레드에서 차단 작업을 수행하고 그런 다음 그 결과를 UI 스레드에
298게시하며, 개발자가 직접 스레드 및/또는 처리기를 처리할 필요가 없습니다.</p>
299
300<p>이를 사용하려면 우선 {@link android.os.AsyncTask}를 하위 클래스로 한 다음 {@link
301android.os.AsyncTask#doInBackground doInBackground()} 콜백 메서드를 구현해야 합니다. 이것은 여러 가지
302배경 스레드에서 실행됩니다. UI를 업데이트하려면 {@link
303android.os.AsyncTask#onPostExecute onPostExecute()}를 구현해야 합니다. 이는 {@link
304android.os.AsyncTask#doInBackground doInBackground()}로부터의 결과를 전달하며 UI 스레드에서 실행되므로,
305안전하게 UI를 업데이트할 수 있습니다. 그런 다음 UI 스레드에서 {@link android.os.AsyncTask#execute execute()}를
306호출하여 해당 작업을 실행하면 됩니다.</p>
307
308<p>예를 들어, 이런 방식으로 {@link android.os.AsyncTask}를 사용하여
309이전의 예시를 구현할 수 있습니다.</p>
310
311<pre>
312public void onClick(View v) {
313    new DownloadImageTask().execute("http://example.com/image.png");
314}
315
316private class DownloadImageTask extends AsyncTask&lt;String, Void, Bitmap&gt; {
317    /** The system calls this to perform work in a worker thread and
318      * delivers it the parameters given to AsyncTask.execute() */
319    protected Bitmap doInBackground(String... urls) {
320        return loadImageFromNetwork(urls[0]);
321    }
322
323    /** The system calls this to perform work in the UI thread and delivers
324      * the result from doInBackground() */
325    protected void onPostExecute(Bitmap result) {
326        mImageView.setImageBitmap(result);
327    }
328}
329</pre>
330
331<p>이제 UI는 안전하고 코드는 더욱 단순해졌습니다. 작업을 작업자 스레드에서 수행되어야 하는
332부분과 UI 스레드에서 수행되어야 하는 부분으로 구분하기 때문입니다.</p>
333
334<p>이 클래스를 사용하는 법을 완전히 숙지하려면 {@link android.os.AsyncTask} 참조를
335읽어보시는 것이 좋습니다. 개괄적인 작동 방식은 아래에 간략히 소개해 놓았습니다.</p>
336
337<ul>
338<li>매개 변수의 유형, 진행률 값과 작업의 최종 값을 제네릭을 사용하여
339지정할 수 있습니다.</li>
340<li>메서드 {@link android.os.AsyncTask#doInBackground doInBackground()}는 작업자 스레드에서 자동으로
341실행됩니다.</li>
342<li>{@link android.os.AsyncTask#onPreExecute onPreExecute()}, {@link
343android.os.AsyncTask#onPostExecute onPostExecute()} 및 {@link
344android.os.AsyncTask#onProgressUpdate onProgressUpdate()}는 모두 UI 스레드에서 호출됩니다.</li>
345<li>{@link android.os.AsyncTask#doInBackground doInBackground()}가 반환한 값이
346{@link android.os.AsyncTask#onPostExecute onPostExecute()}로 전송됩니다.</li>
347<li>언제든 {@link android.os.AsyncTask#publishProgress publishProgress()}를 {@link
348android.os.AsyncTask#doInBackground doInBackground()}에서 호출하여 UI 스레드에서 {@link
349android.os.AsyncTask#onProgressUpdate onProgressUpdate()}를 실행하도록 할 수 있습니다.</li>
350<li>모든 스레드에서 언제든 작업을 취소할 수 있습니다.</li>
351</ul>
352
353<p class="caution"><strong>주의:</strong> 작업자 스레드를 사용할 때 마주칠 수 있는 또 한 가지 문제는
354<a href="{@docRoot}guide/topics/resources/runtime-changes.html">런타임 구성 변경</a>으로 인해 액티비티가 예기치 못하게 다시 시작되는 것입니다
355(예를 들어 사용자가 화면 방향을 바꾸는 경우). 이 경우 작업자 스레드를 소멸시킬 수 있습니다.
356스레드가 재시작될 때 작업을 지속하는 방법과 액티비티가 제거되었을 때 작업을 적절히 취소하는 방법은
357<a href="http://code.google.com/p/shelves/">Shelves</a> 샘플 애플리케이션의 소스 코드를 참조하십시오.</p>
358
359
360<h3 id="ThreadSafe">스레드로부터 안전한 메서드</h3>
361
362<p> 어떤 경우에는 구현하는 메서드가 하나 이상의 스레드에서 호출되는 일도 있습니다. 따라서
363이를 스레드로부터 안전하게 작성해야만 합니다. </p>
364
365<p>이것은 주로 원격으로 호출할 수 있는 메서드에 대해 참입니다. 예를 들어 <a href="{@docRoot}guide/components/bound-services.html">바인딩된 서비스</a> 내의 메서드 등이 해당됩니다.
366{@link android.os.IBinder}에서 구현된 메서드가
367{@link android.os.IBinder IBinder}가 실행되는 프로세스에서 호출될 경우, 해당 메서드는 발신자의 스레드에서 실행됩니다.
368그러나 호출이 다른 프로세스에서 발생하면, 해당 메서드는 시스템이
369{@link android.os.IBinder
370IBinder}와 같은 프로세스에 유지하는 스레드 풀에서 선택된 스레드에서 실행됩니다(프로세스의 UI 스레드에서 실행되지 않습니다).  예를 들어, 어느 서비스의
371{@link android.app.Service#onBind onBind()} 메서드는 해당 서비스
372프로세스의 UI 스레드에서 호출되고, {@link android.app.Service#onBind
373onBind()}가 반환하는 객체에서 구현된 메서드는(예: RPC 메서드를 구현하는 하위 클래스) 해당 풀 안의 여러 스레드에서
374호출되게 됩니다. 서비스에 클라이언트가 하나 이상 있을 수 있으므로, 하나 이상의 풀이
375동시에 같은 {@link android.os.IBinder IBinder} 메서드에 참여할 수 있습니다. 그러므로 {@link android.os.IBinder
376IBinder} 메서드는 스레드로부터 안전하게 구현되어야 합니다.</p>
377
378<p> 마찬가지로 콘텐츠 제공자는 다른 프로세스에서 발생한 데이터 요청을 수신할 수 있습니다.
379{@link android.content.ContentResolver}와 {@link android.content.ContentProvider}
380클래스가 세부적인 프로세스 간 통신의 관리 방식을 숨길 수는 있지만, 이러한 요청에 응답하는 {@link
381android.content.ContentProvider} 메서드(&mdash;{@link
382android.content.ContentProvider#query query()}, {@link android.content.ContentProvider#insert
383insert()}, {@link android.content.ContentProvider#delete delete()}, {@link
384android.content.ContentProvider#update update()} 및 {@link android.content.ContentProvider#getType
385getType()} 메서드&mdash;)가 프로세스의 UI 스레드가 아니라
386콘텐츠 제공자 프로세스의 스레드 풀에서 호출됩니다.  이러한 메서드가 동시에 몇 개의 스레드에서 호출될 수 있으므로,
387스레드로부터 안전하게 구현되어야 합니다. </p>
388
389
390<h2 id="IPC">프로세스 간 통신</h2>
391
392<p>Android는 원격 프로시저 호출(RPC)을 사용한 프로세스 간 통신(IPC) 메커니즘을 제공합니다.
393여기서 메서드는 액티비티나 다른 애플리케이션 구성 요소에 호출되지만
394원격으로 (또 다른 프로세스에서) 실행되고, 결과는 모두 발신자에게 되돌려
395보냅니다. 메서드 호출과 메서드의 데이터는 운영 체제가 이해할 수 있는 수준으로 분해되고,
396로컬 프로세스와 주소 공간에서 원격 프로세스와 주소 공간으로 전송된 다음
397다시 결합되어 여기서 호출에 다시 응답합니다.  그런 다음 반환 값이
398반대 방향으로 전송됩니다.  Android가 이와 같은 IPC 트랜잭션을 수행하는 데 필요한
399모든 코드를 제공하므로, 개발자는 그저 RPC 프로그래밍 인터페이스를 정의하고 구현하는 데에만 집중하면 됩니다. </p>
400
401<p>IPC를 수행하려면 애플리케이션이 반드시 서비스에 바인딩되어야만 하며, 이때 {@link
402android.content.Context#bindService bindService()}를 사용해야 합니다. 자세한 정보는 <a href="{@docRoot}guide/components/services.html">서비스</a> 개발자 가이드를 참조하십시오.</p>
403
404
405<!--
406<h2>Beginner's Path</h2>
407
408<p>For information about how to perform work in the background for an indefinite period of time
409(without a user interface), continue with the <b><a
410href="{@docRoot}guide/components/services.html">Services</a></b> document.</p>
411-->
412