이번엔 쓰레드에 대해 공부하고, 예제를 통해 실습해보도록 하겠습니다.
"쓰레드(Thread)란 무엇인가."
: Thread는 프로그램에서 실행되는 흐름의 단위를 말한다. 일반적으로 하나의 Thread를 가지고 있지만, 환경에 따라 둘 이상의 Thread를 동시에 사용할 수 있다. 이를 멀티쓰레드(multi thread)라고 한다.
위 설명 그대로 하나의 실행단위인데요, 이를 이용해 음악을 들으며 인터넷서핑을 하는 등 동시에 여러 작업을 진행할 수 있습니다.
1. Thread의 선언
Thread() : 디폴트 생성자로 Thread객체를 생성한다. 생성된 객체는 독립적으로 실행되며 고유의 스택을 가진다.
Thread(Runnable runnable) : Runnable 인터페이스 구현객체를 생성한 후 Thread의 생성자로 잔달한다. Runnable은 Run 메소드를 가지는 간단한 인터페이스로써 Thread 대신에 run 메소드를 제공하는 역할을 한다.
2. Thread 예제
2-1)Thread 사용
package com.example.handler_test; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; public class MainActivity extends Activity { int mainValue = 0; int backValue = 0; TextView mainText; TextView backText; Button increaseButton; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mainText = (TextView)findViewById(R.id.mainValue); backText = (TextView)findViewById(R.id.backValue); increaseButton = (Button)findViewById(R.id.increase); backThread thread = new backThread(); thread.setDaemon(true); thread.start(); increaseButton.setOnClickListener(new OnClickListener(){ @Override public void onClick(View arg0) { // TODO Auto-generated method stub mainValue++; mainText.setText("MainValue : "+mainValue); backText.setText("BackValue : "+backValue); } }); } class backThread extends Thread{ public void run(){ while(true){ backValue++; //backText.setText("BackValue : "+backValue); try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } }
자바의 쓰레드는 기본적으로 메인쓰레드와 동등한 자격을 가지며, 모든 쓰레드가 종료되어야 비로소 프로그램이 종료됩니다. 데몬쓰레드는 메인쓰레드가 종료될 때 같이 종료되는 쓰레드이며 backThread는 무한루프를 돌기 때문에 기본옵션으로 생성하면 절대 죽지않는 무적의 쓰레드가 된다나 뭐라나... 그래서 setDaemon(true)를 해주어 메인이 종료될 때 같이 사망하도록 설정했습니다.
자 그럼 위 앱을 실행시켜보겠습니다.
증가버튼을 클릭하니 backValue는 쓰레드로 인해 14가 되었고 mainValue는 버튼클릭으로 1이 되었습니다.
그렇다면 번거롭게 버튼이벤트에 setText를 통해 값을 업데이트하지 않고 쓰레드가 돌면서 1초마다 자동으로 값을 업데이트해주면 어떨까요?
thread안에 주석처리된 backText.setText가 보이시나요?
이 부분의 주석을 풀고 앱을 실행해보겠습니다.
쓰레드님이 사망하였습니다. ㅠㅠㅠㅠ
왜냐면 UI는 메인쓰레드에서만 변경이 가능하거든요....
백그라운드 쓰레드는 내부적인 연산만 해야하며, 다른 쓰레드 소속의 UI를 건드릴수 없습니다. 따라서... 핸들러를 사용해야하나 이건 다음 포스팅때...
자 이번엔 Runnable을 사용한 예제를 확인해보겠습니다.
2-2) Runnable 사용
package com.example.handler_test; import android.app.Activity; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.TextView; public class MainActivity extends Activity { int mainValue = 0; int backValue = 0; TextView mainText; TextView backText; Button increaseButton; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mainText = (TextView)findViewById(R.id.mainValue); backText = (TextView)findViewById(R.id.backValue); increaseButton = (Button)findViewById(R.id.increase); BackRunnable runnable = new BackRunnable(); Thread thread = new Thread(runnable); thread.setDaemon(true); thread.start(); increaseButton.setOnClickListener(new OnClickListener(){ @Override public void onClick(View arg0) { // TODO Auto-generated method stub mainValue++; mainText.setText("MainValue : "+mainValue); backText.setText("BackValue : "+backValue); } }); } class BackRunnable implements Runnable{ public void run(){ while(true){ backValue++; try { Thread.sleep(1000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } }
onCreate에서 BackRunnable 타입의 runnable 객체를 생성한 후, Thread의 생성자에 전달했습니다.
2-1과 같이 Thread를 바로 사용하면 되는데 굳이 Runnable객체를 만들어 사용해야하나 생각하실 수 있으나, 자바는 다중상속을 지원하지 않기 때문에 Thread를 상속받아 사용하면 Thread 이외엔 상속을 받지 못하니 코드의 재사용성에 문제가 있겠습니다.
따라서 Runnable을 사용하면 좀 더 유연하게 개발을 진행할 수 있는 것이죠.
위는 예제 소스입니다.
근데 정작 프로젝트명은 handler_test인데 쓰레드만 구현했네요.
다음 포스팅엔 handler가 추가된 내용으로 올리겠습니다.
좋은 하루 되세요
'Android' 카테고리의 다른 글
안드로이드(android) 핸들러(Handler) 예제2 (2) | 2016.05.27 |
---|---|
안드로이드(android) 핸들러(Handler) 개념 & 예제 (0) | 2016.05.26 |
Android Manifest의 launchMode (1) | 2016.05.19 |
서버와 로컬 파일 사이즈 비교하기 (0) | 2015.11.13 |
블루스택, 윈드로이, 지니모션 구분하기 (0) | 2015.09.04 |