Thread



1. Thread 란


메모리를 할당받아 실행 중인 프로그램을 프로세스라고 하며, 프로세스는 명령어 블록으로 시작점과 졸료점을 가진다. 실행중에 멈출 수 있으며 동시에 수행 가능하고, 프로세스 내에서 실행되는 흐름의 단위를 스레드(Thread)라고 한다.

자바에서는 크게 데몬스레드사용자스레드로 구분할 수 있다.



2. 스레드 종류


  • 사용자스레드(user thread) : foreground에서 실행되는 높은 우선순위를 가진 스레드이다. 자바 프로그램을 실행시키면 JVM은 main() 메서드가 실행되는 main 스레드를 생성하는데 이 main스레드가 사용자 스레드이다. 그리고 main 스레드에서 새로운 스레드를 생성하게 되면 부모 스레들의 속성을 상속받아 기본적으로 사용자 스레드가 되며, 이렇게 생성된 사용자 스레드들이 모두 종료하게 되면 그 프로그램은 종료하게 된다.

  • 데몬스레드(daemon thread) : background에서 실행되는 낮은 우선순위를 가진 스레드 이다. 주로 보조적인 역할을 담당하는데 사용되며, 자바에서 메모리 정리를 해주는 가비지 컬렉터(garbage collector)가 대표적인 데몬 스레드이다. 데몬 스레드와 사용자 스레드의 가장 큰 차이점은 JVM이 데몬 스레드가 작업이 끝날 때까지 기다리지 않는다는 점이다. 사용자 스레드가 모두 종료되면 데몬 스레드는 자동으로 종료된다.



3. Java Thread 클래스 생성자&메소드


Thread 생성자

Thread()
Thread(String s) 스레드 이름
Thread(Runnable r) 인터페이스 객체
Thread(Runnable r, String s) 인터페이스 객체와 스레드 이름

Thread 메소드

static void sleep(long msec)
throws Interrupted Exception
msec 에 지정된 밀리초 동안 대기
String getName() 스레드의 이름 가져오기
void setName(String s) 스레드 이름을 s로 설정
int getPriority() 스레드의 우선 순위를 반환
void setPriority(int p) 스레드의 우선순위를 p값으로
boolean isAlive() 스레드가 시작되었고 아직 끝나지 않았으며 true 끝났으면 false 반환
void join() throws InterruptedCxecption 스레드가 끝날 때 까지 대기
void run() 스레드가 실행할 부분 기술 (오버라이딩 사용)
void suspend() 스레드가 일시정지 resume()에 의해 다시 시작 할 수 있다.
void resume() 일시 정지된 스레드를 다시 시작.
void yield() 다른 스레드에게 실행 상태를 양보하고 자신은 준비 상태로



4. Daemon Thread 예제


public class TestDaemonThread extends Thread{

	public void run(){
		
		// 데몬 스레드인지 확인
		if(Thread.currentThread().isDaemon()){
			System.out.println("Daemon thread");
		}
		else{
			System.out.println("Normal thread executing");
		}
	}
	public static void main(String[] args){

		TestDaemonThread t1=new TestDaemonThread();
		TestDaemonThread t2=new TestDaemonThread();

		//t1을 데몬으로 설정
		t1.setDaemon(true);

		// 스레드 시작 
		t1.start();
		t2.start();
	}
}



5. 멀티 스레드(Multi Thread)


여러 개의 스레드가 동시에 수행되면서 공유할 수 있을 때, 공유되는 부분은 상호 배타적으로 사용되어야 한다.

  • Dead Lock 문제 : 멀티 스레드를 사용할 때 주의할 점 중의 하나로 프로그램에서 스레드를 잘 못 만들면 프로그램의 수행이 이루어 지지 않고 무한 수행하는 Dead Lock 을 만들 수 있다.

  • 임계 영역(Critical section) : 공유 자원을 사용하는 코드 영역을 임계 영역이라 한다. 이 부분에서는 공유 자원을 동시에 수정할 수 없도록 상호 배타적으로 실행될 수 있도록 작성되어야 한ㅇ다.

자바에서 상호 배제 문제를 해결하는 방법은 하나의 스레드만 한 순간에 실행할 수 있도록 synchronized method를 제공하고 있으며 이 스레드가 수행 중이면 다른 스레드는 대기하도록 만들면 된다.

public class Account 
{
    int balance = 1000;
 
    public void withdraw(int money)
    {
        if(balance >= money)
        {
            try
            {
                Thread.sleep(1000);
            }catch(Exception e) { }
                balance -= money;
        }
    }
}
public class Bank extends Thread
{
    static Account obj = new Account();
    public Bank() { }
    public Bank(String name) { super(name); }
    public void run()
    {
        while(true)
        {
            // 멀티 스레드 
            synchronized(obj)
            {
                int money = (int)(Math.random() * 3 + 1) *100;
                if(obj.balance >= money)
                {
                    System.out.println(getName() + " : 원본의 balance : " + obj.balance);
                    System.out.println(getName() + ": 찾는 금액 : " + money);
                    obj.withdraw(money);
                    System.out.println(getName() + " : 수정된 balance : " + obj.balance);
                }else
                {
                    System.out.println("잔액 부족");
                    break;
                }
            }
        }
    }
}
public class Thread6 
{
    public static void main(String args[])
    {
        Bank t1 = new Bank("ATM");
        Bank t2 = new Bank("은행");
        
        t1.start();
        t2.start();
    }
}



7. 타이머 활용


public class Timer extends Objet

백그라운드 Thread로 실행되는 일을 1회 또는 정기적으로 반복 실행되도록 스케줄링 해주는 클래스를 활용할 수 있다.

생성자

Timer() 새로운 타이머를 작성
Timer(boolean isDaemon) daemon으로 실행되는 타이머
Timer(String name) 지정된 이름의 thread를 가지는 타이머
Timer(String name, boolean isDaemon) 지정된 이름의 thread를 가지는 새로운 타이머

메소드

void cancel() 현재 스케쥴 되고 있는 일을 파기해서 타이머를 종료
void schedule(TimerTask task, Date time) 지정한 시간으로 지정한 일이 실행되도록 스케쥴
void schedule(TimerTask task, Date firstTime, long period) 지정한 일이 지정한 시간에 개시되어 기간을 가지고 반복
void schedule(TimerTask task, long delay) 지정한 지연 후에 지정한 일이 실행되도록 스케쥴
void schedule(TimerTask task, long delay, long period) 지정한 일이 지정한 지연 후에 개시되어 기간을 가지고 반복
  • public abstract class TimerTask extends Object implements Runnable

  • Timer에 해 1회 또는 반복해 실행하도록 스케쥴 되는 일

생성자

protected TimerTask() 새로운 타이머 일이 작성

메소드

boolean cancel() 이 타이머 일을 취소
abstract void run() 이 타이머 일에 실행되는 액션
long scheduledExecutionTime() 이 일이 최근 실제로 실행하도록 스케쥴 되었다라는 실행 시간 return