안드로이드 쓰레드 정리

|

안드로이드에서 쓰레드란 어떤 의미일까요?

안드로이드앱은 기본적으로 쓰레드입니다. 우리가 흔히들 액티비티라고 하는것들 그것은 ui를 다루는 쓰레드입니다.

그래서 ui스레드라고도 합니다. 또는 앱의 기본이 되는 쓰레드 이므로 메인쓰레드라고도 합니다.

쓰레드는 실행단위입니다. 그러면서 독립적인 스택공간이 있습니다. 프로세스처럼 독립된 전역메모리 공간은 가지지못합니다.

쉽게 말해서 그냥 함수입니다.


그러나 일반적인 함수는 종속관계가 존재 합니다. 최종적으로 누군가의 부름을 받고 호출되어 실행되는게 우리가 일반적으로 아는 함수입니다.

쓰레드도 비슷합니다. 다른점은 일반적인 펑션콜은 호출 됐다가 실행점이 되돌아오길 기다립니다.

여기에 반해서 쓰레드는 호출되고 기다리지않습니다. 호출한쪽은 자기 볼일을 그대로 계속 보게됩니다.

그래서 동시에 여러개의 앱이 실행되는것도 쓰레드이기 때문에 가능 한것입니다.

또한 당연한 이야기 이겠지만 ui가 붙지않는 쓰레드도 존재합니다. 그것을 서비스라 부릅니다.


쓰레드 를 만드는 방법은 크게 두가지방법이 있고 또하나는 첫번째 방법을 간편하게 만드는 방법까지 총 3가지 방법 있습니다.

첫번째는 run함수를 오버라이딩해서 쓰레드상에서 동작하는 코드들을 그안에 넣는 방법이 있습니다.

두번째는 Runnable 인터페이스에서 상속받아서 그것을 Thread 객체의 생성자에 넣어 주는 방법입니다.


run 함수를 오바라이딩 받아서 하는 방식 입니다. 1000초 간격으로 틱값을 콘솔창에 출력하는 예제입니다.

class MyThread2 extends Thread { 
        @Override 
        public void run() { 
            super.run(); 
 
            while(!Thread.currentThread().isInterrupted()) 
            { 
                try 
                { 
                    Log.d(TAG, "thread 2 tick :" + System.currentTimeMillis()); 
                    sleep(1000); 
                } 
                catch (InterruptedException e) 
                { 
                    Log.e(TAG, "InterruptedException in thread. " + e.getMessage()); 
                    e.printStackTrace(); 
 
                    Thread.currentThread().interrupt(); 
 
                    //Log.d(TAG, "" + Thread.currentThread().isInterrupted()); 
 
                } 
 
 
 
            } 
 
        } 
    } 
 

위의 예제는 다음과 같이 사용되어 집니다.

MyThread2 mThread_test2 = new MyThread2(); 

mThread_test2.start();


다음은 러너블을 상속받아 구현한 예제일부분 입니다. 단순히 클래스를 new 해서 인스턴스를 얻은 다음 start해주면 됩니다.


class MyRunnable implements Runnable { 
 
        @Override 
        public void run() { 
            while(!Thread.currentThread().isInterrupted()) 
            { 
                try 
                { 
                    Log.d(TAG, "thread 3 tick :" + System.currentTimeMillis()); 
                    Thread.sleep(1000); 
                } 
                catch (InterruptedException e) 
                { 
                    Log.e(TAG, "InterruptedException in thread. " + e.getMessage()); 
                    e.printStackTrace(); 
 
                    Thread.currentThread().interrupt(); 
 
                    //Log.d(TAG, "" + Thread.currentThread().isInterrupted()); 
 
                } 
            } 
        } 
    } 


러너블을 이용한 방법은 다음과 같이 사용 되어 집니다.


mThread_test3 = new Thread(new MyRunnable()); mThread_test3.start();

러너블 클래스의 인스턴스를 생서자로 넘겨 줍니다.



간편쓰레드 만드는 방법도 있습니다.


mThread_test1 = new Thread() {     public void run() { 

//..쓰레드 구현 코드     } }; mThread_test1.start();





MyActivity.java
예제소스

package com.gbox3d.threadsample; import android.app.Activity; import android.content.DialogInterface; import android.os.Bundle; import android.os.Handler; import android.util.Log; import android.view.Menu; import android.view.MenuItem; import android.view.View; public class MyActivity extends Activity { public final String TAG="thread_test"; public Thread mThread_test1 = null; public Thread mThread_test2 = null; public Thread mThread_test3 = null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_my); //첫번째 간편 쓰레드 생성하기 findViewById(R.id.button1).setOnClickListener( new View.OnClickListener() { @Override public void onClick(View view) { if(mThread_test1 == null) { //간편 만들기 mThread_test1 = new Thread() { public void run() { while(!Thread.currentThread().isInterrupted()) { try { sleep(1000); Log.d(TAG, "tick :" + System.currentTimeMillis()); } catch (InterruptedException e) { Log.e(TAG, "InterruptedException in thread. " + e.getMessage()); e.printStackTrace(); Thread.currentThread().interrupt(); //Log.d(TAG, "" + Thread.currentThread().isInterrupted()); } } } }; mThread_test1.start(); } else { mThread_test1.interrupt(); mThread_test1 = null; } } } ); //두번째 예제 findViewById(R.id.button2).setOnClickListener( new View.OnClickListener() { @Override public void onClick(View view) { if(mThread_test2 == null) { mThread_test2 = new MyThread2(); mThread_test2.start(); } else { mThread_test2.interrupt(); mThread_test2 = null; } } } ); //3번째 러너블을 이용한 방법 findViewById(R.id.button3).setOnClickListener( new View.OnClickListener() { @Override public void onClick(View view) { if(mThread_test3 == null) { mThread_test3 = new Thread(new MyRunnable()); mThread_test3.start(); } else { mThread_test3.interrupt(); mThread_test3 = null; } } } ); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.my, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } class MyThread2 extends Thread { @Override public void run() { super.run(); while(!Thread.currentThread().isInterrupted()) { try { Log.d(TAG, "thread 2 tick :" + System.currentTimeMillis()); sleep(1000); } catch (InterruptedException e) { Log.e(TAG, "InterruptedException in thread. " + e.getMessage()); e.printStackTrace(); Thread.currentThread().interrupt(); //Log.d(TAG, "" + Thread.currentThread().isInterrupted()); } } } } class MyRunnable implements Runnable { @Override public void run() { while(!Thread.currentThread().isInterrupted()) { try { Log.d(TAG, "thread 3 tick :" + System.currentTimeMillis()); Thread.sleep(1000); } catch (InterruptedException e) { Log.e(TAG, "InterruptedException in thread. " + e.getMessage()); e.printStackTrace(); Thread.currentThread().interrupt(); //Log.d(TAG, "" + Thread.currentThread().isInterrupted()); } } } } }


And