프로세스 : OS로부터 자원을 할당받는 작업의 단위
실행 중인 프로그램을 의미
예시 : 우리가 Java 프로그램을 실행시키면 이 프로그램은 프로세스라는 이름으로 OS 위에서 실행됨

구조 : OS가 프로그램 실행을 위한 프로세스를 할당해 줄 때 프로세스 안에 Code, Data, Memory(Stack, Heap) 을 같이 할당해준다.

쓰레드 : 프로세스가 할당받은 자원을 이용하는 실행의 단위
- 프로세스내에서 일하는 일꾼(코드실행의 흐름)
- 생성 : 프로세스가 작업중인 프로그램에서 실행 요청이 들어오면 쓰레드를 만들어 명령을 처리
- 프로세스 안에는 여러 쓰레드가 있고, 쓰레드들은 실행을 위해 메모리 공간(Heap)을 공유받는다.
- 쓰레드들은 명령 처리를 위해 자신만의 메모리 공간(Stack)도 할당받는다.
- Java 쓰레드 : JVM 프로세스 안에서 실행되는 쓰레드이며, JVM에 의해 Java Main 쓰레드부터 실행됨
싱글 쓰레드 : 프로세스 안에서 하나의 쓰레드만 실행되는 것
- Java에서 main() 메서드만 실행시켰을 때 이것을 싱글 쓰레드라고 함
- Java에서 main() 메서드의 쓰레드를 "메인 쓰레드"라고 부른다
- JVM의 메인 쓰레드가 종료되면, JVM도 같이 종료된다
멀티 쓰레드 : 프로세스 안에서 여러 개의 쓰레드가 실행되는 것
- 하나의 프로세스가 여러 개의 쓰레드를 가질 수 있으며, 이 쓰레드들은 프로세스의 자원을 공유
- Java는 메인 쓰레드 외에 다른 작업 쓰레드를 생성해 여러 개의 실행 흐름을 만들 수 있다
- 장점
- 여러 개의 쓰레드를 통해 여러 작업을 동시에 해서 성능이 좋다
- Stack을 제외한 모든 영역에서 메모리를 공유해 자원을 효율적으로 사용할 수 있음
- 응답 쓰레드와 작업 쓰레드를 분리해 빠르게 응답을 줄 수 있음(비동기)
- 단점
- 동기화 문제가 발생할 수 있음 (자원을 공유하면서 작업을 처리하기 때문에 서로 자원을 사용하려는 충돌이 발생 가능)
- 교착 상태에 걸릴 수 있음 (서로의 자원을 원하는 상태가 되어 상대의 작업의 종료를 계속 기다리는 상태)
데몬 쓰레드
- BackGround에서 실행되는 낮은 우선순위를 가진 쓰레드 (대표적으로 가비지 컬렉터가 있음)
- 다른 쓰레드가 모두 종료되면 데몬 쓰레드는 강제 종료를 당함
사용자 쓰레드
- ForeGround에서 실행되는 높은 우선순위를 가진 쓰레드 (대표적으로 메인 쓰레드가 있음)
- JVM은 사용자 쓰레드의 작업이 끝나면 데몬 쓰레드도 자동으로 종료시켜 버린다.
쓰레드 우선순위
- 쓰레드 작업의 중요도에 따라서 쓰레드의 우선순위를 부여할 수 있음
- 쓰레드는 생성될 때 우선순위가 정해지는데, 이 우선순위는 우리가 직접 지정하거나 JVM에 의해 지정될 수 있음
- setPriority(1~10) : 메서드로 우선순위 설정 가능 (1~10 숫자가 클수록 우선순위가 높음)
쓰레드 그룹
- 서로 관련이 있는 쓰레드들을 그룹으로 묶어서 다룰 수 있음
- 모든 쓰레드들은 반드시 하나의 그룹에 포함되어 있어야 하며, 기본적으로 그룹에 포함되어 있음
- interrupt() : 일시정지 상태인 쓰레드를 실행 대기 상태로 변경
쓰레드 상태
쓰레드 객체가 생성되고 start() 메서드를 통해 실행 대기로 이동
쓰레드는 실행과 대기를 반복하며 run() 메서드를 수행한다.
run() 메서드가 종료하면 실행이 멈춤

일시정지 상태에서는 쓰레드가 실행할 수 없는 상태가 됨
쓰레드가 다시 실행 상태로 넘어가기 위해서는 일시정지 -> 실행대기(interrupt()) 상태로 넘어가야 됨

쓰레드 제어

sleep() : 현재 쓰레드를 지정된 시간동안 멈추게 함 (반드시 InterruptedException 예외처리 해줘야됨)
interrupt() : 일시정지인 상태를 실행 대기 상태로 만듦
join() : 정해진 시간동안 지정한 쓰레드의 작업을 기다림 (시간을 지정하지 않았으면 그 쓰레드의 작업이 끝날 때 까지 기다림, sleep()과 같은 예외처리)
yield() : 남은 시간을 다른 쓰레드에게 양보하고 자신은 실행 대기 상태가 됨
synchronized(동기화) : 한 쓰레드가 진행중인 작업을 다른 쓰레드가 침범하지 못하게 함
wait() : 하나의 쓰레드가 작업을 진행하다가 wait()을 호출하면 Lock을 반납하고 해당 객체의 대기실에서 대기함
notify() : 해당 객체의 대기실에 있는 모든 쓰레드 중 임의의 쓰레드를 호출 (그 쓰레드는 다시 Lock을 받음)
Lock : Synchronized 블럭으로 동기화하면 자동으로 Lock이 걸리고 풀리지만, 같은 메서드 내에서만 Lock을 걸 수 있음 (이런 제약의 해결을 위해 사용)
Condition : wait() & notify()의 문제점인 대기실 내 쓰레드를 구분하지 못한다는 것을 해결한 인터페이스