본문 바로가기

자바

자바 11주차 <쓰레드>

2021년 7월 작성글

 

프로그램 실행 유닛

=프로그램 돌릴 때 메인메모리에 만들어지는 것. 인스턴스(실체)임.

프로그램을 돌린다는 것은 메인메모리에 실행 유닛이 만들어져 실행 공간이 확보되었다는 뜻.

가장 대표적인 실행 유닛은 프로그램임.

 

하나의 프로그램 내 여러 프로세스가 생성되기도 하는데(한 실행 유닛에 또 다른 실행 유닛이 생성되는 것들을 프로세스라고 함)

프로세스의 개수에 따라 싱글 프로세싱이랑 멀티 프로세싱으로 나눔.

 

자바 랭귀지에서는 프로세스가 아니고 객체(오브젝트)가 실행 유닛이 됨.

 

클래스나 프로세스 내에서도 무거운 프로세스와 가벼운 프로세스가 있음.

가벼운 프로세스를 쓰레드라고 함.

 

프로세스 내에서도 잡을 분리할 수 있을 때, 또 쪼갠 것이 쓰레드임. 실행 유닛이 더 작아짐. 프로세스 내에 실행 유닛이 또 만들어짐.

고로 쓰레드란 단위는 되게 작은 단위임.

 

하나의 프로그램 코드만 도는 것-배치 프로그래밍

여러 프로그램이 도는 것-멀티 프로그래밍

한 프로그램 내에 여러 프로세스가 있는 것-멀티 프로세싱

한 프로세스 내에도 여러 쓰레드를 만드는 것-멀티 쓰레드

 

쓰레드를 쓰기 위한 개념이 concurrent 프로세싱.

동시에 진행가능한 컨셉임.

-동기화 : 프로그램 돌릴 때 n개의 실행 유닛이 실행 시점을 맞춰야 할 때.

세마포라는 개념을 사용함.

딜레이 큐라는 함수를 프로세싱 사이에 사용함

-mutual exclusive : 인풋, 아웃풋 할 때 등 동시 수행 안되는 구조. concurrent 프로세싱 시 이런 상황 자주 발생

-communication : 메일박스(메시지 큐), 소켓 등 무얼 받아야 다음 동작 가능한 것.

 

왜 쓰레드가 필요한가?

프로세스 유닛의 문제를 해결하기 위해(싱크를 맞추는 등)

인스턴스를 만들 때 오버헤드와 컨텍트 스위치(문맥 바꾸기-cpu할당 변경)의 오버헤드를 줄여줌.

쓰레드는 사용하는 공간을 공유하기 때문에 프로그램 개발을 쉽게 빠르게 할 수 있음.

 

쓰레드의 구조 : 일반적인 프로세스 유닛은 각각 다른 코드 세그멘트(메서드), 데이터 세그먼트(힙), 스택 세그먼트, 프로세스 인스턴스(=클래스 인스턴스)로 구성됨.

그러나 쓰레드는 코드와 힙 워킹 메모리를 다같이 공유하고 있기 때문에 빨라짐. 컨텍트 스위칭이 필요 없어짐! 스택 포인트만 신경쓰면 됨.

 

쓰레드의 프로세싱 구조.

하나의 클래스 내에 여러 쓰레드가 여러 개 있음. 쓰레드 만큼 cpu가 있으면 각 cpu가 하나의 쓰레드를 맡아서 동시에 돌려버리면 됨.

그러나 cpu가 보통은 하나임. 싱글프로세스임. 그러면 쓰레드의 순서를 정해서 적절하게 번갈아가면서 수행해야 함. 스케줄링 관리가 필요.

 

자바의 쓰레드

쓰레드 클래스에서 만들 수 있음.(run() 함수가 고정됨) : 같은 기능을 돌릴때는 이게 좋음

runnable interface에서도 만들 수 있음. (run이라는 함수를 재 구현해야 함.) : 기능을 변경해야 하는 경우에는 이게 유용함.

용도가 다른거지 장단점이 있는 것은 아님. 적절하게 혼합해서 사용해야 함.

중요한 메서드 void run(), void start(), void seep(long msec) 이런 메서드를 적절하게 사용해서 쓰레드가 잘 돌아갈 수 있게 관리해줘야 함.

 

쓰레드의 라이프 사이클

쓰레드가 new를 통해 생성되면 스타트라는 함수로 실행됨. 레디 상태에 바로 들어갔다가 run()함수를 만나면 수행. join() sleep() suspend() 등의 함수로 멈췄다가 대기했다가 다시 시작하는 과정을 반복함. 다 끝나면 run()을 종료시킴. (보통 stop을 사용하는데 로직에서 알아서 종료시켜주기도 함)

쓰레드가 생성되면 종료될 때 까지 ready run wait을 반복하면서 돌아감.

 

쓰레드 함수를 상속받고 런 함수를 정의하고, 다른 곳에서 쓰레드를 객체로 만들어서 스타트함.

쓰레드를 사용한다는 건 다른 쓰레드랑 동기화를 마치겠다는 의미이므로 concurrent 프로세싱의 유닛이 있을 때 쓰레드를 사용해야 함.

런러블 쓰레드를 정의할 때 런 함수를 다시 정의할 수 있음. 런 메소드를 오버라이딩해 스레드가 수행할 문장 기술 가능.

쓰레드는 new로 바로 만들어지지만 런러블은 쓰레드가 아니라 함수를 정의한 것 뿐이기 때문에 런러블이라는 매개변수를 만들고 그걸 쓰레드로 선언해야 쓰레드가 만들어짐.

thread(runnable)의 생성자가 이 경우에 사용됨.

복잡하지만 런러블 쓰레드마다 런 메서드를 바꿔 사용할 수 있다는 장점이 있음.

일반적인 쓰레드 함수의 런은 고정되어 있음.

이벤트 큐 함수가 중요함 : 메인 함수가 프레임을 동작 시키고 싶을 때 사용하는 메서드.

 

쓰레드 종료 방법 : run()메서드가 끝나면 자동으로 종료하는 방법이 제일 좋음. 게임에서 어떤 조건을 주고 달성되면 자동 종료되게 하는 등!->좌표값을 줘서 그 이상이면 런이 동작하지 않게 해도 됨.

stop()메서드도 있으나 간혹 오류가 생겨서 장려되지 않음.

InterruptException사용 : 인터럽트를 발생시켜서 (타이머등으로) 쓰레드를 종료시킬 수 있음.

타이머 기능을 활용해 인터럽트 익셉션을 유발 시키고(thread.interrupt()) 나중에 isInterripted()나 interrupted()로 인터럽트 여부를 확인해 종료시키면 됨

다른 조건문에 while(stop==false)를 걸어서 종료되게 하는 방법도 있음. 여기서 stop은 스탑 메서드가 아닌 다른 조건임.

혹은 반복문 내에 if조건을 활용해 인터럽트가 생기면 종료되게 설정도 가능

while(true){ if(Tread.isinterrupted) break;}

사용할 방법은 로직에 따라 적합한 것이 다르기 때문에 직접 짜면서 생각하자!

 

잠깐 temporary를 스톱시키는 방법 : suspend(), resume()

 

mutual exclusion 상호 배타성

자바의 synchronized 키워드 : 두개의 유닛이 어떤 공간에 동시에 진입할 수 없는 것. 그게 모니터 개념임. 리드와 라이트, 인풋과 아웃풋 같은 것. 그 공간을 쓰레드, 머츄얼 익스클루션이라고 함.

하나는 생산자, 하나는 컨슈머이고 생산자는 공간에 무언가를 추가하고 컨슈머는 그걸 소모함. 추가하고 소모하는 공간을 모니터라고 함.

모니터 : 생산, 소모 함수를 관리하고 관찰하는 것.

 

 

 

용어정리 : 컨텍트 스위칭(문맥변경)이 무엇인가?

-현재 cpu를 사용중인 프로세스의 cpu제어권이 다른 프로세스로 이양되는 과정.

현재 프로세스가 cpu를 사용하고 있는 상황에서 사용시간이 만료되면 다음 프로세스에게 cpu를 넘겨주어야 함. 스케줄링 알고리즘에 의해 다음cpu를 받을 프로세스가 선택되고, 타이머 인터럽트가 발생해 cpu의 제어권이 운영체제에 넘어가게 됨.

이 과정에서 운영체제는 타이머 인터럽트 처리 루틴으로 가서 직전까지 수행중이던 프로세스의 문맥(프로그램 카운터 등)을 자신의 pcb(프로세스 제어 블록 : 특정한 프로세스를 관리할 필요가 있는 정보를 포함하는 운영체제 커널의 자료구조임)에 저장하고 새로cpu를 받은 프로세스는 자신의 문맥을 pcb로부터 실제 하드웨어로 복원시킴. 이 pcb에 정보를 저장하는걸 문맥을 저장한다고 표현하고, pcb에 전에 저장한 정보를 다시 가져와 적재하는걸 재적재 한다고 이야기함.

 

'자바' 카테고리의 다른 글

람다식(익명함수)  (0) 2021.12.20
자바 스레드를 이용한 간단한 게임  (0) 2021.12.14
자바 스택으로 계산기 구현  (0) 2021.12.12
자바 10주차 <이벤트>  (0) 2021.12.12
자바 9주차 <그래픽>  (0) 2021.12.12