인하대학교 임광수 교수님 수업과 자료 참고
#프로세스란?
: 실행중인 프로그램으로, 디스크에 있는 프로그램이 메모리에 적재되어 운영체제의 제어를 받는 상태이다.
: 자신만의 자원을 가지기 때문에 프로세스 끼리는 서로 독립적으로 작동한다.( 프로세스끼리는 정보를 주고받을 수가 없다._=)
=> 서로 다른 프로세스 간에 데이터를 공유할 때 어떻게 할수 있을지가 이슈로 작용하게 된다.
# 멀티태스킹
: 대부분의 운영체제는 시스템 자원을 효율적으로 사용할 수 있도록 멀티태스킹을 지원한다.
:멀티코어 cpu라면 실제로 다수의 애플리케이션을 동시에 병렬처리하고, 싱글코어라면 다수의 애플리케이션을 병행처리한다. (멀티 프로세싱/ 멀티 스레드 두가지가 있다.)
=> 심지어 하나의 애플리케이션에서도 동시에 수행할 수 있는 다수의 코드 블록이 있을수 있기 때문에 멀티태스킹이 가능하다 => 이를 멀티스레딩이라고 하고, 효율적으로 프로그램이 돌아가도록 한다.
#스레드란?
하나의 프로세스 내부에서 독립적으로 실행되는 하나의 작업 단위를 말하며, 세부적으로는 운영체제에 의해 관리되는 하나의 작업 또는 태스크를 의미한다. => 스레드와 태스크를 바꾸어 사용해도 무방한다.
=> 하나의 실행 흐름으로, 프로세스 내부에 존재하게 된다.
=> 프로세스는 적어도 하나의 스레드를 가지고 있다.
: 프로세스에 비해 실행 환경에 필요한 자원이 매우 적기 때문에 경량 프로세스라고 한다.
=> 하나의 프로세스가 다수개의 작업을 각각 스레드를 이용하여 동시에 사용할 수 있는 것을 멀티스레드 프로세스라고 한다. : 멀티 프로세스에 비해서 상당한 이점을 가지고 있다. (메모리 손실 줄이고, 모든 메모리를 공유할 수 있다.)
+) 동시에 두가지 이상 활동을 할 수 있고, 시스템 자원 소모가 줄어들지만
서로 자원을 소모하다가 충돌이 일어날 수 있고, 코딩이 난해해져 버그 생성 확률이 높아진다.
#JVM, 프로세스, 스레드
: 자바 애플리케이션의 실행 환경인 JVM은 각각 별도의 프로세스로 실행된다.( 스택이나 힙 메모리 영역 공윹)
: 하나의 스레드가 있는 단일 스레드가 속도가 훨 씬 빠르다.
1시간에 7개를 하나씩 차근차근 하는것이 1분마다 7개를 바꿔가면서 처리하는 것보다 효율적이기 때문.
=> 멀티스레드/ 단일 스레드의 차이점
=> 자바 애플리케이션은 적어도 메인 스레드라는 하나의 스래드를 가진다.
: 다수의 스레드로 실행하려면 runnable 인터페이스 또는 Thread 클래스를 상속하는 방법 두가지 중 하나로 작업
스레드를 별도로 추가해야 한다.
=> Thread 객체 생성자: Thread t= new Thread(new Runnableclass());
등으로 안에 runnable 객체를 하나 사용해서 스레드 객체를 생성해주어야 한다.
=> 이 때, implement이므로 run 하는 메소드를 반드시 오버라이딩 해줘야 한다.
=> 또한 따로 runnable 객체를 생성하는 클래스(이름) 없이 무명 객체를 구현할 수도 있다.
# Thread pool
: 스레드들을 미리 만들어 놓은 하나의 풀장이라고 생각하면 된다.
: 요청이 들어올 때마다 스레드를 생성하고 일을 다하면 수거하는 작업은 프로그램 퍼포먼스에 지대한 영향을 줄 수 있다. => 따라서 스레드를 미리 만들어놓아야 한다.
=> 만든 어플리케이션에서 사용자로부터 들어온 요청을 작업 큐에 넣고 스레드풀은 작업 큐에 들어온 task들을 미리 만들어 놓은 thread에 할당한다. 작업을 마치면 어플리케이션에게 결과값을 리턴한다.
1) 스레드 풀의 장점
- 프로그램 성능 저하를 방지할 수 있다.
- 다수의 사용자 요청 (task)들을 처리할 수 있다.
2) 단점
- 너무 많이 만들어 놓았다가 메모리 낭비만 발생할 수가 있다.
- 노는 스레드가 발생할 수가 있다.
(a,b,c 스레드가 있을때 a한테만 일을 떠맡기고 b,c는 놀고있는 상황이 발생한다.)
+) JDK 5부터 Excecutors 클래스를 포함하는 java.util.concurrent 패키지를 이용해 지원한다.
#스레드 생명 주기
: JVM은 스레드의 개수, 스레드의 상태, 우선순위 등 스레드와 관련된 모든 정보를 관리하며, 스레드 스케줄링을 수행한다.
1. Runnable-> start() 메소드를 호출하면 run() 메소드에 설정된 스레드가 runnable상태로 진입한다.
2. Running() -> cpu를 점유하여 실행하고 있는 상태이며, run() 메소드는 JVM 만이 호출 가능하다.
Runnable 상태에 있는 여러 스레드 중 우선순위를 가진 스레드가 결정되면 JVM이 자동으로 호출하여
스레드가 running 상태로 진입한다.
3. Dead -> 모든 스레드가 종료된 상태.
4. Blocked-> cpu가 점유권을 상실된 상태. wait() 메소드에 의해 blocked가 되며, notify() 메소드가 호출되면 runnable 상태가 된다. sleep() 메소드로 blocked된 스레드는 지정시간 후에 runnable 상태가 된다.
# 스레드의 종료
- run() 메소드 실행 종료를 위한 stop() 메소드
-> 호출 즉시 스레드를 종료하므로 사용중인 자원을 낭비할 가능성이 있어서 가급적 사용하지 않는다.
- 안전한 종료를 위해 반복문, interrupt() 메소드를 사용한다.
=> 스레드는 메인이 끝나도 계속 돌아가게 된다.
하지만 이러한 스레드도 join() 메소드를 이용해 제어할 수 있다.
-> join()을 이용하면 해당 스레드가 종료되기 기다렸다가 다음으로( main 함수 가 스레드 종료 후에 종료된다.)
+) join 메소드가 없으면 메인 함수가 다 끝난 뒤에 스레드가 돌아가게 된다.
# 스레드 우선순위
-멀티태스킹에서 스레드 개수가 CPU 코어 개수보다 많다면 스레드 스케줄링이 필요하다.
- 자바에선 우선순위 방식과 순환할당 방식을 사용한다.
#데몬 스레드
: 데몬 스레드란 주 스레드의 작업을 돕는 보조적인 역할을 수행하는 스레드이다.
=>다른 스레드를 모두 종료하면 자동으로 종료된다.
ex) 워드 프로세스의 자동 저장, 미디어 플레이어의 동영상 및 음악 재생... etc
=> 주 스레드가 종료되면(워드 프로세스, 미디어 플레이어, JVM...) 같이 종료된다.
=> 데몬스레드 아닐 때/ 데몬 스레드일때 두가지 결과가 다르게 나온다.
# 스레드 동기화
: 작업들 사이의 수행 시기를 맞추는 것이다.
=> 사건이 동시에 일어나거나, 일정한 간격을 두고 일어나도록 시간의 간격을 조정한다.
- 이유: 스레드가 같은 프로세스 내의 자원을 공유하면서 작업하는 경우에 서로의 작업이
다른 작업에 영향을 주기 때문이다.
- 해결 방법: 스레드의 동기화를 위해서 임계영역의 잠금을 사용한다.
=> 임계영역이란? : 병렬 컴퓨팅에서 둘 이상의 스레드가 동시에 접근해서는 안되는 공유자원에 접근하는 코드.
- 동기화 블록에 진입한 스레드가 락이 걸리고, 그 코드를 실행할 동안 다른 스레드는 동기화 블록 앞에서 락이 풀릴때까지 기다려야한다. / 고로 한 스레드 작업을 끝낼때까지 다른 스레드는 실행되지 못한다.
동기화하지 않으면 중간에 다른 스레드가 중구난방으로 들어와서 출력되어버릴 수 있다.
#대기와 통보
: 동기화 메소드와 블록을 이용하면 공유 자원은 보호할 수 있지만, 특정 스레드가 필요 없이 오랜 시간 동안 락을 걸수 있다. => object 클래스는 객체의 락과 관련된 wait(), notify(), notifyall() 메소드를 제공하여 이런 상황을 해결할 수 있다. (이 메소드들은 동기화 블록 안에서 사용해야 한다.)
wait()를 만나면 해당 스레드는 해당 객체의 락 권한을 놓고 대기하며, notify() 메소드를 통해 다음 메소드를 깨운다.
# 스레드 협업
: 자원을 공유하지만 하나는 생산하고, 다른 하나는 소비하는 형태의 작업으로 두 스레드 사이에 협업이 필요하다.
'Computer Science > Java' 카테고리의 다른 글
본격 JVM 해부하기 (0) | 2022.11.24 |
---|---|
JAVA) 이벤트 구동 프로그래밍 (0) | 2019.12.07 |
Java -GUI 프로그래밍 (0) | 2019.12.05 |
Java) 입출력 스트림- 11주차 수업 (0) | 2019.12.03 |