실행 중인 프로그램, 프로그램을 수행하는 데 필요한 데이터와 메모리 등의 자원 그리고 쓰레드(일꾼)로 구성
프로세스 내에서 실제 작업을 수행. 모든 프로세스(공장)는 최소한 하나의 쓰레드(일꾼)를 가지고 있다.
멀티 태스킹(멀티 프로세싱) : 동시에 여러 프로세스를 실행시키는 것
멀티 쓰레딩 : 하나의 프로세스 내에 동시에 여러 쓰레드를 실행시키는 것
두 개의 작업을 하나의 쓰레드(싱글 쓰레드)로 처리하는 경우와 두 개의 쓰레드로 처리하는 경우
왠지 두 개의 쓰레드로 처리하면 시간이 짧게 소요될 것이라고 생각하겠지만 예상과 다르게 거의 같다. 아니 오히려 더 오래 걸리게 된다. 그 이유는 쓰레드 간의 작업 전환(Context Switching)에 시간이 걸리기 때문이다. 작업 전환시 현재 진행 중인 작업의 상태 등의 정보를 저장하고 읽어 오는 시간이 소요된다.
Thread 클래스를 상속받으면 다른 클래스를 상속받을 수 없다. (Java는 다중상속을 허용하지 않음) 그래서 Runnable 인터페이스를 구현하는 방법이 일반적이다.
쓰레드가 입출력(I/O)처리를 위해 기다리는 것
만약에 입력받는 작업과 출력 받는 작업을 하나의 쓰레드로 처리한다면 사용자가 입력을 마칠 때까지 아무 일도 하지 못한다. 하지만 두 개의 쓰레드로 처리한다면 사용자의 입력을 기다리는 동안 다른 쓰레드가 작업을 처리할 수 있다.
쓰레드는 우선순위(Priority)라는 속성(멤버변수)을 가지고 있는데, 작업의 중요도에 따라 쓰레드의 우선순위를 서로 다르게 지정하여 특정 쓰레드가 더 많은 작업 시간을 갖도록 할 수 있다.
void setPriority(int newPriority) 쓰레드의 우선순위를 지정한 값으로 변경한다.
int getPriority() 쓰레드의 우선순위를 반환한다.
public static final int MAX_PRIORITY = 10 //최대 우선 순위
public static final int MIN_PRIORITY = 1 //최소 우선 순위
public static final int NORM_PRIORITY = 5 //보통 우선 순위
//JVM은 1 ~ 10단계 WinOS는 1 ~ 32단계
ThreadGroup getThreadGroup() //쓰레드 자신이 속한 쓰레드 그룹을 반환한다.
void uncaughtException(Thread thread, Throwable e) //처리되지 않은 예외에 의해 쓰레드 그룹의 쓰레드가 실행이 종료되었을 때, JVM에 의해 이 메서드가 자동적으로 호출된다.
boolean isDaemon() //쓰레드가 데몬 쓰레드인지 확인한다. 데몬 쓰레드면 true 반환
void setDaemon(boolean on) //쓰레드를 데몬 쓰레드로 또는 사용자 쓰레드로 변경한다. 매개변수 on의 값을 true로 지정하면 데몬 쓰레드가 된다.
//setDaemon(boolean on)은 반드시 start()를 호출하기 전에 실행되어야 한다.
//그렇지 않으면 IllegalThreadStateException이 발생한다.
쓰레드의 실행을 제어(스케줄링)할 수 있는 메서드가 제공된다. 이것들을 이용하여 효율적인 프로그램을 작성할 수 있다.
static void sleep(long millis) //천분의 일초 단위
static void sleep(long millis, int nanos) //천분의 일초 + 나노초
void interrupt() //쓰레드의 interrupted상태를 false => true 변경
boolean isInterrupted() //쓰레드의 interrupted상태를 반환
static boolean interrupted() //현재 쓰레드의 interrupted상태를 반환 후, false로 변경
void suspend() //쓰레드를 일시정지 시킨다.
void resume() //suspend()에 의해 일시정지된 쓰레드를 실행대기 상태로 만든다.
void stop() //쓰레드를 즉시 종료시킨다.
void join() //작업이 모두 끝날 때까지
void join(long millis) //천분의 일초 동안
void join(long millis, int nanos) //천분의 일초 + 나노초 동안
한 번에 하나의 쓰레드만 객체에 접근할 수 있도록 객체에 락(lock)을 걸어서 데이터의 일관성을 유지하는 것.
//1. 메서드 전체를 임계 영역으로 지정
public synchronized void calcSum() { //임계 영역
//... //임계 영역
} //임계 영역
//2. 특정한 영역을 임계 영역으로 지정
synchronized(객체의 참조변수) { //임계 영역
//... //임계 영역
} //임계 영역