[Java] thread에 대해 예습하기.
220628 과제
1. 프로세스와 스레드
- 프로세스: 실행 중인 프로그램, 자원과 스레드로 구성.
- 스레드: 프로세스 내에서 실제 작업을 수행. 모든 프로세스는 최소한 하나 이상의 스레드를 가지고 있다.
* 찾아본 영상에서는 프로세스를 공장, 스레드를 일꾼에 비유.
- 하나의 새로운 프로세스를 생성하는 것보다 하나의 새로운 스레드를 생성하는 것이 더 적은 비용이 든다.
2. 멀티스레드의 장단점
- 장점
① 시스템 자원을 보다 효율적으로 사용 가능
② 사용자에 대한 응답성이 향상된다. (여러 응답 가능 ex. 게임하며 채팅 같은.)
③ 작업이 분리되어 코드가 간결해진다.
- 단점
① 동기화에 주의해야 한다.
② 교착상태가 발생하지 않도록 주의해야 한다.
③ 각 스레드가 효율적으로 고르게 실행될 수 있게 해야한다.(특정 스레드가 작업할 기회를 갖지 못하는 경우가 있음)
* 멀티스레드를 만드는 것은 쉬우나 고려해야 할 사항들이 많다.
3. 스레드의 구현과 실행
① Thread클래스를 상속: java는 단일 상속만 가능하다보니 다른 클래스를 상속받을 수 없어 주로 ②의 방법 사용.
② Runnable 인터페이스를 구현
5. 스레드의 실행 - start()
- 스레드를 생성한 후에 start()를 호출해야 스레드가 작업을 시작한다.
- 작업 순서는 os의 스케쥴러가 실행 순서를 결정한다. (os에 종속적.)
6. start()와 run()
- 메인 메소드가 start 메소드를 호출하면 start 메소드는 새로운 스택을 호출하고 새로운 스택에 run메소드를 넣은 뒤 종료된다.
- 서로 다른 스택에서 작업하게 된다. (run메소드를 바로 호출하면 한 스택 내에서 실행되므로 반드시 start메소드 호출할 것.)
7. main 스레드
- main 메서드의 코드를 수행하는 스레드
- 스레드는 '사용자 스레드'와 '데몬 스레드' 두 종류가 있음.
- 실행 중인 사용자 스레드가 하나도 없을 때 프로그램은 종료.
- main 스레드가 종료되더라도 다른 스레드의 작업이 남은 경우 프로그램은 종료되지 않는다.
8. 싱글스레드
① 싱글 스레드
- 작업이 하나씩 실행된다.
- 작업 간에 교차되지 않는다.
② 멀티 스레드
- 여러 작업이 동시에 실행된다.
- 작업 간에 교차될 수 있다.
- 작업이 전환되면서 시간이 조금 더 소요될 수 있다.
11. 스레드의 I/O blocking
- 외부의 입력 혹은 출력이 있는 동안 다른 작업을 미리 수행함으로써 총 작업 소요 시간을 줄일 수 있다.
14. 스레드의 우선순위
- 작업의 중요도에 따라 스레드의 우선순위를 다르게 하여 특정 스레드가 더 많은 작업시간을 갖게 할 수 있다.
- 우선순위가 같은 경우에는 비슷한 시간을 번갈아가며 수행
- 한 작업의 우선순위가 더 높은 경우에는 우선순위가 더 높은 쪽에 시간을 먼저 더 할애한다.
- 우선순위를 지정한다고 해도 os의 스케쥴러에 고려되는 정도이지 완벽하게 반영되진 않는다.
16. 스레드 그룹
- 서로 관련된 스레드를 그룹으로 묶어서 다루기 위한 것.
- 모든 스레드는 반드시 하나의 스레드 그룹에 포함되어있어야 한다.
- 스레드 그룹을 지정하지 않은 경우에는 main 스레드 그룹에 속한다.
- 자신을 생성한 스레드(부모 스레드)의 그룹과 우선순위를 상속받는다.
17. 스레드 그룹의 메서드
18. 데몬 스레드(Deamon Thread)
- 일반 스레드의 작업을 돕는 보조적인 역할을 수행
- 일반 스레드가 모두 종료되면 자동적으로 종료
- 가비지 컬렉터, 자동저장, 화면 자동갱신 등에 사용된다.
- 무한 루프와 조건문을 이용해서 실행 후 대기하다가 특정 조건이 만족되면 작업을 수행하고 다시 대기하도록 작성된다.(프로그램이 언제 종료될지 모르기 때문에)
20. 스레드의 상태
21. 스레드의 실행 제어
- 스레드의 실행을 제어할 수 있는 메서드를 통해 보다 효율적인 프로그램을 작성할 수 있다.
30.스레드의 동기화
- 멀티 스레드 프로세스에서는 다른 스레드의 작업에 영향을 미칠 수 있다.
- 진행중인 작업이 다른 스레드에게 간섭받지 않게 하려면 '동기화'가 필요하다.
- 한 스레드가 진행중인 작업을 다른 스레드가 간섭하지 못하게 막는 것을 의미한다.
- 동기화하려면 간섭받지 않아야하는 문장들을 '임계영역'으로 설정해야 한다.
- 임계영역은 lock을 얻은 단 하나의 스레드만 출입 가능(객체 1개에 락1개)
34. wait()과 notify()
- 동기화하는 경우 데이터 보호는 가능하나 한 번에 한 스레드만 접근 가능한 점 때문에 효율이 떨어지기 때문에 두 메소드를 사용한다.
- wait(): 객체의 lock를 풀고 스레드를 해당 객체의 waiting pool에 넣는다.
- notify(): waiting pool에서 대기중인 스레드 중의 하나를 깨운다. (랜덤으로 하나)
- notifyAll(): waiting pool에서 대기중인 스레드 모두를 깨운다. (많은 스레드가 waiting pool에 있는 경우 어느 한 스레드가 계속 깨워지지 않을수도 있기 때문에 보통 notifyAll을 사용.)