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 |