Thread는 프로그램에서 실행되는 흐름의 단위.
환경에 따라 프로그램에서 두개 이상의 Thread를 동시에 실행 시킬 수 있다 (Multi-Thread)
ex) 동영상 시청과 인터넷 쇼핑을 동시에 하는 것
Thread(): Default constructor로 Thread object을 생성. 이렇게 생성된 객체는 독립적으로 실행되며 고유의 Stack을 갖는다.
Thread(Runnable runnable): Runnable interface 구현객체를 생성 후 Thread constructor로 전달. Runnable은 Run 메소드를 가지는 간단한 interface로서 Thread 대신 run 메소드를 제공한다.
public class MainActivity extends Activity
{
int m_thread_val = 0;
int b_thread_val = 0;
TextView tv_m_thread_val;
TextView tv_b_thread_val;
Button increaseButton;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContextView(R.layout.activity_main);
mainText = (TextView)findViewById(R.id.mainValue);
backText = (TextView)findViewById(R.id.backValue);
increaseButton = (Button)findViewById(R.id.increase);
backThread th = new backThread();
th.setDaemon(true); // 메인 Thread가 종료시 같이 종료되는 Thread. 기본 옵션으로 생성하면 죽지않는 Thread가 됨.. ㅎㅎ
th.start(); // Thread 시작
increaseButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0)
{
mainValue++;
tv_m_thread_val.setText("Value in main thread: " + m_thread_val);
tv_b_thread_val.setText("Value in back thread: " + b_thread_val);
}
});
}
class backThread extends Thread
{
public void run()
{
while(true)
{
b_thread_val++;
// tv_b_thread_val.setText("Value in Back thread : " + b_thread_val);
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
}
앱을 실행시켜 보면
Before clicking the button
m_thread_val: 0
b_thread_val: 0
After clicking the button
m_thread_val: 1
b_thread_val: 12
backThread부분의 while loop내부에서 주석 처리된 부분 풀고 앱을 실행하면 thread가 죽는다.. Why?
-> UI는 MainThread에서만 변경이 가능해!
Background thread는 내부적인 연산만 해야해. 다른 Thread에 속해있는 UI를 조작 할 수 없어.
어떻게 해결할 수 있을까?
=> Use Handler!! (will be discussed in a seperate article :) )
public class MainActivity extends Activity
{
int m_thread_val = 0;
int b_thread_val = 0;
TextView tv_m_thread_val;
TextView tv_b_thread_val;
Button increaseButton;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContextView(R.layout.activity_main);
mainText = (TextView)findViewById(R.id.mainValue);
backText = (TextView)findViewById(R.id.backValue);
increaseButton = (Button)findViewById(R.id.increase);
// backThread th = new backThread();
// th.setDaemon(true);
// th.start();
BackRunnable runnable = new BackRunnable();
Thread th = new Thread(runnable);
th.setDaemon(true);
th.start();
increaseButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View arg0)
{
m_thread_val++;
tv_m_thread_val.setText("Value in main thread: " + m_thread_val);
tv_b_thread_val.setText("Value in back thread: " + b_thread_val);
}
});
}
class BackRunnable implements Runnable
{
public void run()
{
while(true)
{
b_thread_val++;
//tv_b_thread_val.setText("Value in Back thread: " + b_thread_val);
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}
}
}
onCreate에서 runnable object을 생성한 후, Thread constructor에 전달.
그럼 여기서 생각나는 질문이 첫번째 example처럼 Thread를 바로 사용하면 되지 왜 굳이 Runnable object를 만들어서 사용하는 걸까?
=> Java는 다중상속을 지원 안해! 그래서? -> Thread를 상속받아 사용하면 Thread이외의 클래스를 상속 못받겠지? -> 코드의 재사용성이 낮아져!
그래서 Runnable을 implement하면 개발에 있어서 좀 더 유연하지자낭 :)