- 스레드(Thread)
: 프로세스 내에서 실행되는 흐름의 단위(작업 단위)
: 메모리를 할당받아 실행 중인 프로그램을 프로세스라고 함
: 프로세스 내의 명령어 블록으로 시작점과 종료점을 가짐
: 실행 중에 멈출 수 있으며 동시에 수행 가능
: 병렬적으로 처리 여러 개의 루틴을 가질 수 있는 게 장점
1) JVM에 의해 하나의 프로세스가 발생하고 main() 안의 실행문들이 하나의 스레드임
2) main() 이외의 또 다른 스레드를 만들려면 Thread 상속 or Runnable 인터페이스를 구현해야 함
3) 다중 스레드 작업 시에는 각 스레드끼리 정보를 주고받을 수 있음
- 스레드 클래스(java.lang.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() |
스레드의 이름을 s로 설정 |
void setName(String s) |
스레드의 이름을 s로 설정 |
void start() |
스레드를 시작 run() 메서드 호출 |
int getPriority() |
스레드의 우선순위를 반환 |
void setpriority(int p) |
스레드의 우선순위를 p값으로 |
boolean isAlive() |
스레드가 시작되었고 아직 끝나지 않았으면 true 끝났으면 false 반환 |
void join() throws InterruptedException |
스레드가 끝날 때까지 대기 |
void run() |
스레드가 실행할 부분 기술 (오버 라이딩 사용) |
void suspend() |
스레드가 일시정지 resume()에 의해 다시 시작할 수 있다. |
void resume() |
일시 정지된 스레드를 다시 시작. |
void yield() |
다른 스레드에게 실행 상태를 양보하고 자신은 준비 상태로 |
- Thread 생명주기
1. Runnable (준비상태)
: 스레드가 실행되기 위한 준비단계
: CPU를 점유하고 있지 않으며 실행(Running 상태)을 하기 위해 대기하고 있는 상태
: 코딩 상에서 start( ) 메서드를 호출하면 run( ) 메서드에 설정된 스레드가 Runnable 상태로 진입한다. “Ready “ 상태라고도 합니다.
2. Running (실행상태)
: CPU를 점유하여 실행하고 있는 상태이며 run() 메서드는 JVM만이 호출 가능함.
: Runnable(준비상태)에 있는 여러 스레드 중 우선순위를 가진 스레드가 결정되면 JVM이 자동으로 run( ) 메서드를 호출하여 스레드가 Running 상태로 진입한다.
3. Dead (종료 상태)
: Running 상태에서 스레드가 모두 실행되고 난 후 완료 상태. ( Done 상태)
4. Blocked (지연 상태)
: CPU를 점유권을 상실한 상태.
: 후에 특정 메서드를 실행시켜 Runnable(준비상태)로 전환.
: wait( ) 메서드에 의해 Blocked 상태가 된 스레드는 notify( ) 메서드가 호출되면 Runnable 상태로 간다.
: sleep(시간) 메서드에 의해 Blocked 상태가 된 스레드는 지정된 시간이 지나면 Runnable 상태로 간다.
- 스레드 생성
: 자바에서 스레드를 생성하는 방법은 2가지가 있음
1) Runnable 인터페이스를 구현하는 방법
2) Thread 클래스를 상속받는 방법
: 두 방법 모두 스레드를 통해 작업 내용을 run() 메서드에 작성하면 됨
- Runnable 인터페이스 이용
: JDK 라이브러리 인터페이스고 run() 메서드만 정의되어 있음
class PrimeRun implements Runnable {
long minPrime;
PrimeRun(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
}
PrimeRun p = new PrimeRun(143);
new Thread(p).start();
- Thread 클래스 이용
: Thread 클래스로부터 제공되는 run() 메서드 오버 라이딩해서 사용
class PrimeThread extends Thread {
long minPrime;
PrimeThread(long minPrime) {
this.minPrime = minPrime;
}
public void run() {
// compute primes larger than minPrime
. . .
}
}
PrimeThread p = new PrimeThread(143);
p.start();
: run() 메서드가 종료하면 스레드는 종료됨.
: 스레드를 계속 실행시키려면 run() 메서드를 무한루프 되어야 함.
: 한번 종료된 스레드는 다시 시작할 수 없음 -> 스레드 객체를 다시 생성해야 함.
: 한 스레드에서 다른 스레드를 강제 종료할 수 있음.
- Daemon Thread
: 동일한 프로세스 안에서 주 스레드의 작업을 돕는 보조적인 역할을 하는 스레드
: 다른 스레드를 서비스해주면서 다른 스레드가 모두 종료되면 자신도 종료됨
: 워드 프레 세서의 자동 저장, 미디어 플레이어의 동영상 및 음악 재생, GC 등에 사용됨
: 프로그램이 종료되는 것을 막지 않으며 GC나 메인 스레드가 데몬 스레드임
: 스레드를 생성하고 setDaemon(true)를 설정하면 됨
=> 주의할 점은 thread.start() 전에 호출되어야 한다
=> 만약 호출되기 전에 실행될 시 IllegalThreadStateException이 발생함
: 스레드가 시작하기 전에 설정해야 함
boolean isDaemon() // 스레드가 데몬 스레드인지 확인한다. 데몬 스레드이면 true 반환한다.
void setDaemon(boolean on)
// 스레드를 데몬 스레드 또는 사용자 스레드로 변경한다.
// (매개변수 on의 값을 true로 지정하면 데몬 스레드가 된다.)
- 스레드 우선순위(Priority)
: 자바에서 각 스레드는 우선순위(priority)에 관한 자신만의 필드를 가지고 있음
: 이러한 우선순위에 따라 특정 스레드가 더 많은 시간 동안 작업을 할 수 있도록 설정할 수 있음
static int MAX_PRIORITY | 스레드가 가질 수 있는 최대 우선순위를 명시함. (10) |
static int MIN_PRIORITY | 스레드가 가질 수 있는 최소 우선순위를 명시함. (1) |
static int NORM_PRIORITY | 스레드가 생성될 때 가지는 기본 우선순위를 명시함. (5) |
: getPriority()와 setPriority() 메서드를 통해 스레드의 우선순위를 반환하거나 변경할 수 있음
: 스레드의 우선순위가 가질 수 있는 범위는 1부터 10까지이며, 숫자가 높을수록 우선순위 또한 높아진다
: 하지만 스레드의 우선순위는 비례적인 절댓값이 아닌 어디까지나 상대적인 값
: 우선순위가 10인 스레드가 우선순위가 1인 스레드보다 10배 더 빨리 수행되는 것이 아님
: 단지 우선순위가 10인 스레드는 우선순위가 1인 스레드보다 좀 더 많이 실행 큐에 포함되어, 좀 더 많은 작업 시간을 할당받을 뿐이다
: 스레드의 우선순위는 해당 스레드를 생성한 스레드의 우선순위를 상속받게 됩니다.
: main() 스레드의 우선순위 값은 초기값이 5
- 스레드 우선순위는 변경 가능
- void setPriority(int priority)
- int getPriority()
- JVM의 스케쥴링 규칙
- 철저한 우선순위 기반
- 가장 높은 우선순위의 스레드가 우선적으로 스케쥴링
- 동일한 우선순위의 스레드는 돌아가면서 스케쥴링(라운드 로빈)
- 스레드 종료
: run() 메서드에 예외처리에 return을 넣어 스스로 종료
: 타 스레드에서 강제 종료 시 interrupt() 메서드를 호출하면 InterruptedException 발생
- 멀티 스레드(multi thread)
: 여러 개의 스레드가 동시에 수행되면서 공유할 수 있을 때 공유되는 부분은 상호 배타적으로 사용되어야 한다.
: 자신이 속한 프로세서의 메모리를 공유하므로 시스템 자원의 낭비가 적음
- Dead Lock 문제
: 멀티 스레드를 사용할 때 주의할 점 중의 하나로 프로그램에서 스레드를 잘못 만들면 프로그램의 수행이 이루어지지 않고 무한 수행하는 Dead Lock을 만들 수 있음
- 임계 영역(critical section)
: 공유 자원을 사용하는 코드 영역을 임계 영역이라 한다.
: 이 부분에서는 공유 자원을 동시에 수정할 수 없도록 상호 배타적으로 실행될 수 있도록 작성되어야 한다.
- 자바에서 상호 배제 문제를 해결하는 방법
: 자바는 한순간에 하나의 스레드만 실행할 수 있는 synchronized method 제공
: 한 스레드가 synchronized method를 수행 중이면 다른 스레드는 대기
- 처리방법
- 공유 자원에 접근하는 메서드의 앞에 synchronized 메서드로 지정
- 공유 자원을 사용하는 영역을 synchronized(객체명)의 블록으로 지정
스레드 그룹(thread group)
: 서로 관련이 있는 스레드를 하나의 그룹으로 묶어 다루기 위한 장치
: 폴더를 생성해서 관련된 파일들을 함께 넣어서 관리하는 것처럼 함
: 모든 스레드는 반드시 스레드 그룹에 포함되어 있어야 함
: 우리가 생성하는 모든 스레드 그룹은 main 스레드 그룹의 하위 스레드 그룹이 되며 스레드 그룹을 지정하지 않고 생성한 스레드는 자동적으로 main 스레드 그룹에 속하게 됨
참고 자료
https://raccoonjy.tistory.com/15
http://tcpschool.com/java/java_thread_multi
https://coding-factory.tistory.com/279