안드로이드 스레드 통신. 핸들러와 Runnable. (Android Thread Communication. Handler and Runnable)

2019. 6. 24. 22:26


1. 안드로이드 핸들러. (Android Handler)

지난 글 [안드로이드 스레드. 핸들러와 메시지. (Android Thread. Handler and Message)]에서, 안드로이드의 가장 기본적인 스레드 통신 방법인 핸들러(Handler)와 메시지(Message)에 대해 살펴보았습니다. 루퍼(Looper)와 메시지큐(MessageQueue), 그리고 핸들러(Handler)와 메시지(Message)에 대해 알아보고, 메시지 전달 및 처리 흐름 내에서 각 요소들이 수행하는 역할들에 대해서 설명했습니다.


핸들러를 통해 메시지를 전달하는 방식은 간단하고 명료합니다. 수신 측 스레드에 핸들러 객체를 생성한 다음 handleMessage() 메서드를 오버라이드하고, 송신 측 스레드에서는 핸들러 객체에서 메시지 객체를 할당하여 값을 채운 다음 sendMessage() 메서드로 보내면 됩니다. 구체적인 절차와 코드 작성 방법은 [안드로이드 스레드. 핸들러와 메시지. (Android Thread. Handler and Message) - 4. 안드로이드 핸들러(Handler) 사용 방법.]에서 확인할 수 있습니다.


그런데 핸들러(Handler)를 통해 스레드 통신을 수행할 때, 반드시 Message 객체만 사용해야 하는 것은 아닙니다. 경우에 따라 Message를 사용하는 방법보다 간단하게 스레드 통신을 수행할 수 있는 방법이 있는데요, 바로 Runnable 객체를 사용하는 방법입니다.

1.1 핸들러(Handler) 사용 목적과 Runnable

[안드로이드 스레드. 핸들러와 메시지. (Android Thread. Handler and Message)]에서, 핸들러(Handler)가 스레드의 메시지 큐(Message Queue)에 메시지(Message)를 보내거나, 수신된 메시지(Message)를 처리할 때 사용하는 클래스라고 설명했었는데요. 사실, 보다 정확한 표현을 위해서는, 여기에 한 가지가 더 추가되어야 합니다. 바로 Runnable 객체도 보낼 수 있다는 것이죠.

Handler Message and Runnable


안드로이드 개발 참조문서의 Handler 항목(https://developer.android.com/reference/android/os/Handler)을 보면, Handler에 대한 설명이 아래의 문장으로 시작되는 것을 확인할 수 있습니다.


A Handler allows you to send and process Message and Runnable objects associated with a thread's MessageQueue.


번역해보면, "핸들러(Handler)는 스레드의 메시지 큐(MessageQueue)와 관련된 MessageRunnable 객체를 보내고 처리할 수 있게 만들어준다"는 내용입니다. 그런데 여기서, Runnable 객체를 보낼 수 있다는 문장은, 구체적으로 무엇을 의미하는 걸까요? Message를 보내는 것과 Runnable을 보내는 것은 어떤 차이가 있는 걸까요?


메시지(Message)와 핸들러(Hander)를 사용하여 스레드 통신을 수행하는 주 목적은, 핸들러를 통해 데이터를 전달하여, 전달된 데이터 처리를 위해 작성된 대상 스레드의 코드가 실행되도록 만드는 것입니다. 이를 위해, 메시지 객체(what, object, arg1, arg2, ...)에 값을 채워 수신 스레드의 핸들러에 보내고, 수신 측 스레드에서는 handleMessage() 메서드를 오버라이드하여 수신된 메시지 객체를 처리하기 위해 작성된 코드를 실행하는 것이죠.


그런데 Message 객체를 사용하는 방법에는 조금 번거로운 절차가 필요합니다. 메시지에 저장된 데이터의 종류를 식별하기 위한 값을 상수로 정의해야 하고, handleMessage()에서는 상수 값에 따른 처리 코드를 조건 문으로 작성해야 합니다. 그리고 메시지를 보내는 측에서도, 전달할 데이터 종류에 따라 별도의 Message 객체를 구성하고 값을 채워 보내야 합니다. 오직, 대상 스레드에 작성된 코드를 실행하기 위해서 말이죠.


여기서, 한 가지 질문을 던져 보겠습니다. 핸들러 사용의 주 목적이 대상 스레드의 코드를 실행하는 것이라면, 메시지를 통해 데이터를 전달하는 번거로운 과정을 거치지 말고, 그냥 "실행 코드"를 바로 보내면 되지 않을까요? 즉, 핸들러에 실행 코드가 담긴 객체를 보내고, 대상 스레드에서는 수신된 객체의 코드를 직접 실행하도록 만드는 것입니다.


네. 여기서 말하는 "실행 코드가 담긴 객체". 그것이 바로 Runnable 객체입니다.

Handler Runnable 스레드 통신 흐름


자, 이제 핸들러를 통해 Runnable 객체를 보낼 수 있다는 문장의 의미가 조금 이해 되시나요? 좀 더 나아가서, [안드로이드 스레드(Android Thread)]를 살펴보고 그 내용을 정확히 이해했다면, 그리고 [안드로이드 개발 참조문서. Runnable]를 확인한 적이 있다면, 대상 스레드에서 실행될 코드를 Runnablerun() 메서드에 작성한다는 것도 눈치채셨을 것 같네요.

2. 핸들러(Handler)로 Runnable 객체 보내기.

Runnable 객체를 보내는 방법도, 수신 스레드 측의 Handler 참조를 사용한다는 점에서는 Message 객체를 보내는 방법과 동일합니다. 하지만 Runnable 객체로 보내고 전달된 코드가 실행되는 부분은 조금 다른데요, 먼저 다음 그림을 통해 Runnable 객체를 보내는 절차를 확인해 보시죠.

Handler로 Runnable 객체를 보내는 절차.


2.1 Runnable 수신 스레드 : Handler 객체 생성.

핸들러를 사용해 Runnable 객체를 보내기 위해서는, 먼저 수신 스레드에서 핸들러 객체를 생성해야 합니다. [안드로이드 스레드. 핸들러와 메시지. (Android Thread. Handler and Message.) - 4. 안드로이드 핸들러(Handler) 사용 방법]에서 설명했듯이, Handler 객체는 생성과 동시에 해당 스레드에서 동작 중인 루퍼(Looper)와 메시지 큐(MessageQueue)에 자동으로 연결됩니다.


    Handler mHandler = new Handler() ;


자, 수신 스레드에서 할 일은 이게 전부입니다. [안드로이드 스레드. 핸들러와 메시지. (Android Thread. Handler and Message.) - 4. 안드로이드 핸들러(Handler) 사용 방법] 에서는 핸들러를 생성하고, 수신 메시지를 처리하기 위해 handleMessage() 메서드를 오버라이드했었지만, Runnable 객체를 보낼 때는 이 과정이 필요없습니다. 실행될 코드는 이미 Runnable 객체의 run() 메서드 안에 담겨져 있으니까요.

2.2 Runnable 송신 스레드 : Runnable 객체 생성 및 run() 메서드 오버라이드.

이제 송신 측 스레드에서 Runnable 객체를 만들고 run() 메서드를 오버라이드해야 합니다.


    class NewThread extends Thread {
        Handler handler = mHandler ;

        @Override
        public void run() {
            while (true) {
                // create Runnable instance.
                Runnable runnable = new Runnable() {
                    @Override
                    public void run() {
                        // TODO : 실행 코드 작성.
                    }
                }

                // send runnable object.
                handler.post(runnable) ;
            }
        }
        
    }

2.3 Runnable 객체 보내기

Runnable 객체를 만들고 run() 메서드를 오버라이드하고 나면, 마지막으로 할 일은 Handler.post() 메서드를 사용하여, 앞서 생성한 Runnable 객체를 수신 측 스레드로 보내는 것입니다.


    handler.post(runnable) ;


[안드로이드 스레드. 핸들러와 메시지. (Android Thread. Handler and Message.) - 4. 안드로이드 핸들러(Handler) 사용 방법]에서 Message 객체를 보내기 위해 sendMessage() 메서드를 사용한다는 것 확인했을텐데요, Runnable 객체를 보낼 때는 아래 표에 정리된 "post"로 시작하는 이름의 메서드를 사용합니다.


메서드 프로토타입 설명
boolean post(Runnable r) Runnable 객체를 전달. (핸들러에 연결된 메시지큐에 추가.)
boolean postAtFrontOfQueue((Runnable r) Runnable 객체를 메시지큐의 가장 앞에 추가.
boolean postAtTime(Runnable r, long uptimeMillis) uptimeMillis로 지정된 시각에, Runnable 객체 전달.
boolean postAtTime(Runnable r, Object token, long uptimeMillis) uptimeMillis로 지정된 시각에, Runnable 객체 전달. r을 취소하는데 사용될 수 있는 token 인스턴스 사용 가능.
boolean postDelayed(Runnable r, long delayMillis) 현재 시각에서 delayMillis 만큼의 시간 후에, Runnable 객체 실행.
boolean postDelayed(Runnable r, Object token, long delayMillis) 현재 시각에서 delayMillis 만큼의 시간 후에, Runnable 객체 실행. token 인스턴스를 통해 r의 실행 취소 가능.


"post" 다음에 AtFrontOfQueue, AtTime, Delayed 등의 접미사가 붙은 메서드는 메시지큐 내에서의 Runnable 객체의 위치와 Runnable 객체가 처리되는 시점을 직접 지정하기 때문에, Runnable 객체의 처리 우선순위 또는 스레드 실행 대기 시간 등에 영향을 미칠 수 있습니다. 그러므로 각 메서드의 정확한 동작 방식과 그에 따른 주의사항에 대해 정확히 인지하고 사용하시길 바랍니다.

3. Runnable 인터페이스.

보통 자바 개발자들이 Runnable 인터페이스를 처음 접하게 되는 순간은, 새로운 스레드를 실행할 때 입니다. [안드로이드 스레드(Android Thread)]에서 살펴보았듯이, Runnable 인터페이스를 implements 한 다음, Thread 인스턴스에 전달하고, 생성된 Thread 인스턴스의 start() 메서드를 실행하는 과정을 통해 새로운 스레드를 만들고 실행할 수 있습니다.


    class NewRunnable implements Runnable {
        NewRunnable() {

        }

        public void run() {
            // TODO : thread running codes.
        }
    }

    NewRunnable nr = new NewRunnable() ;
    Thread t = new Thread(nr) ;
    t.start() ;


그런데 스레드를 생성할 때 작성한 Runnable 인터페이스의 코드를 보고, 단순히 Runnable 인터페이스가 새로운 스레드를 실행할 때만 사용된다거나, 심지어 Thread 클래스처럼 스레드 실행 코드가 구현된 클래스로 착각하는 경우가 있습니다.


하지만 명확히 알아두어야 할 것은, 새로운 스레드를 실행하는 역할은 Thread 클래스의 역할입니다. Runnable은 단지 새로운 스레드에서 실행될 run() 메서드를 가지는 인터페이스일 뿐인 것이죠.


Runnable 인터페이스는 단 하나의 메서드, run() 메서드만 가집니다. Runnable 인터페이스를 상속한 클래스가 오버라이드해야 할 단 하나의 메서드이자, Runnable 객체를 참조하는 곳에서 호출할 메서드인 run() 메서드.


Thread 생성 시에 Runnable 인터페이스를 implements 하는 것은 굳이 Thread 클래스를 상속하지 않아도 스레드 실행 코드를 작성할 수 있기 때문이지, Runnable의 용도가 새로운 스레드를 만드는 것에만 국한된 것은 아니라는 것입니다.


Runnable 객체는 어디서든 사용될 수 있습니다. 코드 실행이 필요한 곳이라면 어디서든 Runnable 인터페이스를 상속받아 run() 메서드를 작성한 다음, 해당 객체를 전달해 run() 메서드를 실행할 수 있는 것입니다.

Runnable 인터페이스


다소 설명이 길어졌는데요, 요약하자면, Runnable 인터페이스가 사용된 코드를 보고, 단순히 새로운 스레드를 실행하는 코드로만 해석하는 실수를 하지 말라는 것입니다.

4. 핸들러(Handler)와 Runnable을 사용한 스레드 통신 예제.

이제 예제를 통해 Runnable 객체를 전달하여 스레드 간 통신을 수행하는 방법을 알아보겠습니다. 예제는, [안드로이드 스레드 예제. 스레드로 고민해보기. (Android Thread UseCase)]에서 핸들러와 메시지를 사용하여 만들어본 디지털 시계를, Message 대신 Runnable을 사용하여 만들어보겠습니다.


아래 예제 코드와 [안드로이드 스레드 예제. 스레드로 고민해보기. (Android Thread UseCase) - 5. 스레드 적용. 스레드 간 통신 적용하기.]에서 작성된 코드를 비교하면, MessageRunnable 사용 방법의 차이를 확인할 수 있습니다.

4.1 Runnable을 전달을 통해 스레드 간 통신을 수행하는 앱 구조 설계.

Runnable을 핸들러로 전달하여 현재 시각을 표시하는 방법의 실행 절차는 아래와 같은 구조를 가집니다.


[STEP-1] 앱 구조 설계. (핸들러를 통해 Runnable 전달)

앱 구조 설계. (핸들러에 Runnable 전달)


4.2 메인액티비티 레이아웃 작성.

메인액티비티 화면에는 아래 그림과 같이 화면 가운데 현재 시각을 표시할 수 있는 텍스트뷰를 배치합니다.

[STEP-2] 메인액티비티 레이아웃 작성.
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior"
    tools:context=".MainActivity"
    tools:showIn="@layout/activity_main">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="48sp"
        android:text="00:00:00"
        android:id="@+id/clock"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

4.3 Runnable 객체 전달 기능 구현.

자, 이제 Runnable 객체의 run() 메서드에 현재 시각을 표시하는 코드를 작성하고 핸들러를 통해 전달하여, 메인스레드에서 실행되도록 만들겠습니다.


[STEP-3] Runnable 객체에 현재 시각 갱신 코드 작성 후, 메인 스레드로 전달.
public class MainActivity extends AppCompatActivity {

    TextView clockTextView ;
    private static Handler mHandler ;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // ... 코드 계속.

        mHandler = new Handler() ;

        // 핸들러로 전달할 runnable 객체. 수신 스레드 실행.
        final Runnable runnable = new Runnable() {
            @Override
            public void run() {
                Calendar cal = Calendar.getInstance();

                SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
                String strTime = sdf.format(cal.getTime());

                clockTextView = findViewById(R.id.clock);
                clockTextView.setText(strTime);
            }
        } ;

        // 새로운 스레드 실행 코드. 1초 단위로 현재 시각 표시 요청.
        class NewRunnable implements Runnable {
            @Override
            public void run() {
                while (true) {

                    try {
                        Thread.sleep(1000);
                    } catch (Exception e) {
                        e.printStackTrace() ;
                    }

                    mHandler.post(runnable) ;
                }
            }
        }

        NewRunnable nr = new NewRunnable() ;
        Thread t = new Thread(nr) ;
        t.start() ;
    }
}

4.4 실행 결과.

예제 작성을 완료하고 실행하면, 현재 시각을 1초 마다 화면에 표시하는 것을 확인할 수 있습니다.

스레드 간 통신 적용 예제 실행 화면


5. 참고.

.END.


ANDROID 프로그래밍/THREAD , , , , , , , , ,

  1. Blog Icon
    사랑합니다

    읽다보니 조금 의아한 점이 생기는데요.
    멀티스레드 자체가 다양한 실행 흐름을 동시에 주기 위해서 사용하는 거잖아요??
    근데 메인 스레드의 메시지 큐에 이런식으로 러너블 객체든 메시지든 큐에다 저장하고 루퍼를 통해 메인 스레드의 핸들러에서 이 데이터를 처리해주면,
    결국 다른 스레드에서는 매개변수나, what따위만 넣은 메시지를 보내거나 메인 스레드의 핸들러에서 돌릴 러너블 객체를 보내는 것.

    즉 결국은 모두 메인 스레드의 핸들러에서 코드가 돌아간다는 말 아닌가요??

    제가 여태까지 소홀히 읽어서 그런건가 잘 모르겠는데, 결국 스레드로 만들어진 애들은 메시지 큐안에서 순서에 맞게 돌아갈 뿐,
    모든 것이 메인 스레드의 핸들러에서 처리된다고 보면 되나요? (만약 핸들러를 받는 측이 메인 UI 스레드만 있다고 가정할때!)

  2. 일단 메인 스레드에서 핸들러 코드가 실행된다는 것은 이해하신 것 같습니다.

    하지만 스레드의 기본으로 돌아가서,
    새로 만든 스레드는 메인 스레드와 "병행적으로" 실행됩니다.
    그리고 새로운 스레드에서 메인 스레드로 무언가 전달해야 할 필요가 있으면 그 정보를 핸들러로 보내는 것이죠.

    아마 Runnable 때문에 헷갈리셨을 것 같은데요, 새로운 스레드에서 실행되는 코드와 Runnable을 사용하여 메인 스레드로 전달하는 코드는 완벽히 구분되어야 합니다.

    본문에서 핵심적으로 다루는 내용은 핸들러의 주 사용 목적과 방법입니다. 스레드의 기본 내용이 흔들려서는 안됩니다.

    의미가 잘 전달 되었는지 모르겠네요.

    아래 질문에서 조금 더 보충하겠습니다.

  3. Blog Icon
    사랑합니다

    만약 스레드 간에 서로 통신할 필요가 없는(예를 들면 메인 액티비티의 화면전환이 필요하지 않은 경우) 그런 프로그램이라면, 하나의 클래스에서 다양한 스레드를 만들어도, 핸들러를 구현할 필요 없으니 얘네들은 실행시키면 동시에 여러 스레드가 생겨서 돌아가는거고, 위 경우에는, 서로 스레드가 통신을 해야 하니까, 순서 흐름이 매우 중요하므로, 핸들러라는 곳에서 스레드 속의 코드를 순서에 맞게 실행한다. 정도로 이해하면 될까요?

  4. 일단 스레드 간 통신이 필요없는 곳이라면 핸들러없이 구현하는 것은 맞는 얘기입니다.

    하지만 스레드 통신이 필요한 경우, "순서 흐름이 매우 중요하므로, 핸들러라는 곳에서 스레드 속의 코드를 순서에 맞게 실행한다"는 내용은 잘 못 이해하신 것 같습니다.

    기본적으로 핸들러는 실행 순서와 관련이 없습니다.

    핸들러는 대상 스레드에 메시지를 전달하는 게 목적인 방법이지, 실행 순서를 조절하기 위한 방법이 아닙니다. 그리고 핸들러 사용으로 인해 실행 순서가 조절되는 것도 아닙니다.

    스레드의 실행 순서라는 것은 개발자의 의도에 의해 결정되는 것이지, 단순히 핸들러의 사용 유무에 따라 결정되는 것이 아닙니다.

    음, 글로만 쓰려니, 답글 적기가 쉽지 않네요.

    일단 설명은 이 정도로만 남길게요.
    잘 이해가 안가시면, 다시 질문글 남겨주세요.

    감사합니다.

  5. Blog Icon
    사랑합니다

    이정도만 해도 정말 감사합니다. 스레드 관련 5편글 다 읽어보긴 했는데 나중에 각잡고 다시 정독해보겠습니다!

  6. 일단 다양한 자료를, 많이 보시길 추천드립니다.

    제 블로그의 글 외에도, 다른 블로그 글이나 책, 구글링 검색 자료 등을 잘 읽어보시면, 좀 더 넓은 범위의 지식을 확보하실거라 생각이 드네요.

    감사합니다.

  7. Blog Icon
    와!

    안드로이드 기초 공부하고 있는데 어떤 구글링에서도 Thread 관련해서 이렇게
    세세하게 설명해준 자료가 없었는데 너무너무 감사합니다!
    안드로이드 마스터 하는 그날까지 주소 즐찾 해서 계속 공부하겠습니다~

  8. 블로그에 내용이 많이 없어서 송구스러울 따름입니다.
    더 좋은 내용 남길 수 있도록 노력하겠습니다.

    방문해 주셔서 감사합니다.

  9. Blog Icon
    사랑합니다

    글을 다시 읽고 머릿속을 정리해서 남겨봅니다.

    스레드는 병행적으로 프로세스 안에서 실행될 수 있는 흐름들을 말하고,
    동시에 여러 스레드가 실행되는 것이 가능 하지만,
    스레드간의 통신을 위해서는, 핸들러와 루퍼를 통해 통신을 처리해야 한다.

    통신이 필요가 없을때는, 그냥 하나의 프로세스에 여러개의 스레드를 동시에 실행시킬 수 있으니
    한 번에 여러 개의 작업을 동시에 할 수 있다.

    정도로 이해하면 될까요?

    그리고 추가로, 반드시 UI작업은 메인 스레드에서 처리되야 하기 때문에, 러너블로 작성된 코드를 post나 직접 만든 클래스, 혹은 runOnUiThread()를 통해 넘겨주어, 메인 스레드에서 해당 러너블 코드가 동작하게 하여 UI를 변경할 수 있다.

    까지요!

  10. 네. 대체적으로 잘 이해하신 것 같지만...
    역시 개념 이해 만으로는 아쉽지요.

    다양하고 복잡한 구조의 소프트웨어 설계 경험을 쌓으시면 좀 더 확실한 이해와 활용이 가능하실 거라 생각합니다.

    감사합니다.

  11. Blog Icon
    학생입니다

    비록 경험 적은 학생임에도, 작성자분이 내공이 깊으신 개발자이심이 느껴집니다. 이 글을 작성하기까지의 학식과 경험을 간접적으로 상상해볼 수 있는 글이었습니다. 감사합니다. 많이 배웠습니다. 제가 본 것은 안드로이드 스레드이지만, 이것만 보더라도 대단한 실력자임을 단번에 알 수 있었습니다. 빈말이 아니라 실제로 만나서 조언을 듣고 따르고 싶을정도입니다. 지식 생태계를 위해 힘써주심에 다시한번 더 감사드립니다.

  12. 아이고.. 과분한 칭찬에 몸둘바를 모르겠네요. ^^;; 하지만 아쉽게도... 전 그리 대단한 실력자가 아닙니다. ㅜㅜ

    하루하루 주어진 일 해내는 것도 버거운, 비루한 실력의 개발자일 뿐... ㅜㅜ

    그래도 이런 칭찬과 격려의 글을 보면, 조금 더 열심히 갈고 닦아야겠다는 생각이 드네요.

    칭찬 댓글, 정말 감사합니다.

  13. Blog Icon
    이상하네요

    runnable객체는 run()메소드에새 생성하면 안될텐데요..

  14. 앗! 그런가요?
    왜, runnable 객체를 run() 메서드에서 생성하면 안될까요?

  15. Blog Icon
    유니나1125

    안드로이드 FW 개발 처음 공부하는 직딩입니다. 책보다 설명이 더 잘되어 있어서 책보다가 궁금한 점이 여기서 해소가 되네요. 좋은 자료 감사합니다.(_ _)

  16. 안드로이드 "FW 개발"이라고 하시는 걸 보니, Embedded 쪽 일을 하시나 보네요.

    블로그에 정리한 내용들이 도움이 되었으면 좋겠습니다.

    감사합니다.

  17. 잘 읽었습니다. 도움이 많이 되었습니다.

  18. 너무 늦게 답글 달아서 죄송합니다.
    방문해 주셔서 감사합니다.

  19. Blog Icon
    비틀

    handler.snedMessage()와 handler.post()의 메소드를 같이 쓰게 된다면, 메시지 큐에 message 객체와 runnable 구현 객체가 같이 있을 수 있겠군요.

    만약 message 객체와 runnable 구현 객체가 거의 동시에 메세지 큐로 보내진다면 message와 runnable의 실행순서는 때때로 바뀔 수 있나요??

  20. "거의 동시에"라는 말은 "사람"의 인식 능력에 따른 기준이고, 컴퓨팅 환경에서는 결국 사건 발생의 전후 관계가 명확히 결정됩니다.

    메시지 "큐"라는 단어에서 알 수 있듯이, message 든 runnable이든 먼저 큐에 먼저 들어간 것이 먼저 실행됩니다. FIFO(First-In First-Out)으로 동작하니까요.

    원하시는 답변이 되었는지 모르겠네요.
    또 궁금한 내용이 있으면 질문글 남겨주세요.

    감사합니다.

  21. 안녕하세요.
    기재하신 쓰레드 시리지는 몇번을 반복해서 읽고 있습니다. 정말 도움이 많이 되는 글입니다.
    그런데 개인적으로 좀 애매한 부분들이 해결되지 않고 궁금함이 남아서 질문 좀 드리겠습니다!
    멀티쓰레드에서 동시성과 병렬성이 있는데 동시성은 동시에 실행되는 것처럼 시분할로 눈속임을 하는것이고 병렬성은 코어수만큼 쓰레드가 생성되고 실제로 완전 병렬로 실행되는 것으로 알고 있습니다.

    1.
    안드로이드에서 Thread를 하나 생성한다는 가정하에, 이 쓰레드는 코어수랑 관련이 없는 것 같은데(코어 수 보다 많이 생성 가능) 어떻게 해석해야 될까요?

    2.
    일반적으로 쓰레드를 생성해서 이렇게 진행하는 것은 동시성 프로그래밍인가요 아니면 병렬성인가요?


    기본적인 건데 아무리 다른데 찾아봐도 모르겠어서 질문좀 드렸습니다.
    답변 주시면 감사하겠습니다!


  22. 안드로이드의 스레드가 다른 시스템의 스레드에 비해 특별한 것은 없습니다.
    그냥 일반적인 운영체제에서 사용하는 스레드와 동일합니다.

    스레드는 반드시 CPU 코어 당 하나를 생성해야 하는 것은 아니고요. 시스템(운영체제)에서 지원하는 만큼 생성해서 실행할 수 있습니다.

    스레드를 CPU 코어와 관계없이 사용한다면 동시성 프로그래밍에 가까울테고, 스레드를 CPU 코어에 하나씩 실행한다면, 병렬성 프로그래밍이라고 할 수 있을 것 같네요.

    음.. 정확한 답변인지는 확신이 안서네요.

    감사합니다.