안드로이드/프로그래밍

쓰레드, 스레드, Thread, 핸들러, Handler

에어버스 2015. 1. 28. 17:06
쓰레드, 스레드, Thread, 핸들러, Handler 

각 쓰레드는 고유 스택을 가진다.
Main 쓰레드(쓰레드 생성자)와 별도의  CPU 시간을 할당 받음.
쓰레드로 구현할 코드는 run() 에 넣는다.
start() 호출하면 run() 자동 실행.
setDaemon(true) : Main 쓰레드 종료되면 호출된 쓰레드 자동 종료.

A. Thread 상속받아 구현
다른 클래스 상속을 못받음.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
     TextView output;
    
     ConnectSocket conSock = new ConnectSocket();
     conSock.setDaemon(true);
// 메인쓰레드 종료되면 쓰레드 자동종료시킴
     conSock.start();
        
    class ConnectSocket extends Thread {
        public void run() {
            while (true) {
                ....
                output.post(new Runnable() {
                        public void run() {
                            output.setText(c);
                        }
                });
           }
       }
    }      


9번 부터 쓰레드 클래스 정의하고
5번에서 쓰레드 객체 만들고 7번에서 쓰레드 실행한다.
쓰레드에서 처리할 코드는 12번에 넣는다.

B. Runnable 로 구현
다른 class 상속받아 수정이 필요한경우 class 상속받고, runnable 구현

1
2
3
4
5
6
7
8
9
10
11
12
BackRunnable r = new BackRunnable();
Thread t = new Thread(r);
t.setDaemon(true);
t.start();

class BackRunnable implements Runnable {
    public void run() {
        ....
    }
}
 

C. Handler 쓰레드간 데이터 주고받기 (윈도우의 메시지 처리기와 유사)

- 쓰레드간 Msg 전달
- 하나의 쓰레드를 가짐 (1:1 매칭)
- sub 쓰레드는 Main 쓰레드의 값을 참조 가능하나 Main 쓰레드의 UI 출력은 불가하므로
이때 handler 로 값을 전달하여 Main 쓰레드에서 값을 받아 출력하면 된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
    TextView m;
    int mValue;

    class ConnectSocket extends Thread {
        public void run() {
            h.sendEmptyMessage(0); // 메시지 전달하면 자동으로 handlerMessage() 호출됨
            // m.setText(mValue); // 오류 발생하므로 handler 이용

        }
    }
    
    Handler h = new Handler() {
        public void handlerMessage(Message msg) {

            if (msg.what == 0) { // 메시지 종류에 따라 처리, 여러 쓰레드에서 handler 공유 할때 이용
                m.setText(mValue);
            }
        }
    };

 

D. 루퍼, Looper (윈도우의 이벤트 처리기와 유사)

- Msg Queue 에 메시지 전달되면 handler 가 스스로 가져가지 못하므로 Looper 가 쓰레드로 전달해준다.
- App 실행 시 생성되는 Main 쓰레드는 루퍼를 가지고 있으나, 쓰레드는 Looper를 직접 구현해야 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
    TextView m;
    int mValue;

    class ConnectSocket extends Thread {
        Handler MainHandler;
        
        ConnectSocket(Handler h){ // 생성자
            MainHandler = h;
        }
        
        public void run() {
            Looper.prepare(); // 메시지 큐 생성
            Looper.loop();                      
        }
    }

    Handler h = new Handler() {
        public void handlerMessage(Message msg) {
            Message msg = Message.obtain(); // 매번 new 연산자 쓰면 메모리 낭비, 속도저하문제로 이걸쓴다.
                                                               // 전달하는 값이 없는 경우 인수없이 호출

            if (msg.what == 0) {
                m.setText(mValue);
            }
        }
    MainHandler.semdMessage(msg); // Main 쓰레드로 메시지 전달    
    };
 
    

Message.obtain(handler 부모핸들러, int what, int arg1, int arg2, Object obj);
부모핸들러.sendMessage(msg);
- what : 여러 쓰레드에서 하난의 핸들러 공유 시 쓰레드 구분자 역활
- 정수형 전달은 arg1, arg2 이용
- 3개 이상 전달 혹은 int형 이외의 자료형을 전달시에는 obj 이용