<TIL> java_Thread
2021.09.30
스레드
하나의 응용 어플리케이션이 실행되면 생성되는 것을 프로세스라고 하는데
스레드는 이 프로세스의 Sub 프로세스라고 생각하면된다.
즉, 하나의 프로세스 안에 여러개의 멀티 스레드를 생성해 동작 가능하고 동시에 비동기적으로 작업되는 코드 실행 개념이다.
자바의 멀티태스킹
멀티태스킹은 한번에 여러 일을 동시에 진행하는 것을 말한다.
자바에서는 프로세스가 존재하지 않고 스레드를 기본 개념으로 코드를 실행시키며 JVM에 의해 자바의 스레드가 스케줄되어 실행된다.
스레드 여러개가 실행 준비 단계가 되어 스케줄되면 이를 멀티스레드라고 부른다. 즉, 동시에 여러개를 실행시킬 준비가 된 상태라는 것이다.
이때 스레드 실행 특징은 스케줄된 여러개의 스레드가 순서대로 빠르게 실행되어 동시에 진행되는 것처럼 하는 것이 아니라 랜덤으로 한개의 스레드를 실행하고 실행 중간에도 다른 스레드고 가서 실행시키고 또 랜던하게 이동하여 또 다른 스레드를 실행시켜 멀티태스킹을 실현한다.
스레드 만들기
스레드를 만드는 방법은 2가지가 있으며
- Thread 클래스 이용
- Runnable 인터페이스 이용
위 두가지 객체를 이용해 생성이 된다.
Thread 클래스
개발자의 스레드 코드를 만들 수 있게 요소를 담은 클래스
스레드 생성
class 클래스이름 extends Thread { @Override public void run(){ // 오버라이딩 ........ } }
위처럼 클래스를 상속받았지만 run 메서드를 구현하여야 한다.
run 메서드를 오버라이딩하지 않으면 Thread 클래스의 run 메서드가 실행되어 아무 일도 없이 리턴되도록 작성되어서 스레드가 바로 종료된다.
메인메서드에서 스레드 생성 및 실행
public void main(String[] args){ 클래스데이터타입 레퍼런스변수 = new 클래스데이터타입(); // 생성자함수 레퍼런스변수.start(); // 스레드 실행 함수 }
Thread 클래스를 상속받은 클래스의 인스턴스를 메인메서드에 생성하고 해당 인스턴스변수.start()로 스레드를 실행시켜준다.
Runnable 인터페이스
스레드를 만들수 있게 설계된 인터페이스로 추상메서드를 run() 하나만 가지고 있다.
스레드 생성
class 클래스이름 implements Runnable { @Override public void run(){ // 오버라이딩 ........ } }
인터페이스라 run 메서드를 오버라이딩해야만 오류가 나지 않는다.
추가로 Thread는 클래스라 다중상속이 불가능한데, Runnable은 인터페이스이기 때문에 다중상속이 가능하여 여러 기능을 한 클래스에 부여할 수 있다.
메인메서드에서 스레드 생성 및 실행
public void main(String[] args){ Thread 레퍼런스변수 = new Thread(new 클래스데이터타입()); // 생성자함수 레퍼런스변수.start(); // 스레드 실행 함수 }
Runnable은 실제 스레드를 만들기보다는 스레드클래스로 바로 실행시킬 수 있게 준비시켜주는 인터페이스로 스레드 실행함수를 사용하기 위해 Thread 클래스 생성자 함수의 인자로 넘겨주어 인스턴스를 생성한다.
스레드 정보
스레드에 관련된 정보는 JVM에 의해서 관리되고 Thread 메서드로 읽어올 수 있다.
정보 상세 내역
필드명/데이터타입
스레드 이름/스트링
스레드 ID/정수
스레드의 PC(Program Count)/정수
스레드 상태/정수
스레드 우선순위/정수
스레드 그룹/정수
스레드 레지스터 스택/메모리 블록
스레드 상태
스레드의 생명주기의 상태를 뜻하고 총 6가지로 분류된다.
-
NEW
스레드가 생성되었지만 아직 실행할 준비가 되지 않은 상태로 start() 메소드가 호출되면 Runnable 상태가 된다. -
Runnable
스레드가 현재 실행 중인 상태이거나 실행준비가 되어 스케줄링을 기다리는 상태 -
TIMED WAITING
스레드가 sleep(long n) 메서드에 의해 n밀리초만큼 대기하는 상태를 말한다. 대기시간 뒤에는 다시 Runnable 상태가 됨. -
BLOCK
스레드가 입출력 작업(I/O)을 실행하면 입출력이 완료될때까지 멈춘 상태를 말한다. I/O 작업 실행 시 JVM이 자동으로 해당 스레드를 BLOCK 상태로 바꾸고 다른 스레드를 스케줄링한다. -
WAITING
스레드가 객체에 대해 객체.wait()를 실행해 다른 스레드가 객체.notify() 또는 객체.norifyAll()로 불러줄때까지 무한정 기다리는 상태이다. -
TERMINATED
스레드가 종료된 상태이며 더 이상 어떠한 상태로 변이할 수 없다.
스레드 우선 순위
JVM은 기본적으로 스케줄링된 스레드들을 랜덤하게 이동하면서 작동시키지만
스레드의 정보에는 우선순위가 매겨져있어 차이가 있다면 우선순위가 높은쪽을 먼저 실행시킨다.
우선순위 체계
- 최댓값 = 10
- 최솟값 = 1
- 보통 값(디폴트) = 5
우선순위 세팅 메서드
void setPriority(int newPriority)
스레드 종료
스레드를 종료시키는 방법은
스스로 종료시키는 방법과
강제로 종료시키는 방법이 존재하고
종료된 스레드는 다시 사용할 수 없다.
강제종료
메인메서드 내 어디서든 스레드레퍼런스변수명.interrupt()를 실행하면 스레드가 강제로 종료된다.
flag를 통한 종료
boolean 값을 반환하는 flag 멤버변수를 선언해두고
false로 초기화해준뒤, flag 변수에 해당하는 boolean 값을 true로 바꾸는 함수를 실행키기고 if문을 스레드의 run() 메서드 내부에 작성하여 flag 값이 true일때는 return시켜 종료시킨다.
스레드 동기화
스레드는 기본적으로 동시다발적으로 실행시키기위한 실행형식으로 비동기적이다.
하지만 스레드도 동기적으로 작동해야될때가 있는데 바로 공유데이터에 접근하는 경우이다. 같이 사용하게 되는 데이터를 동시에 여러 스레드가 접근하여 값을 조정하게 되면 데이터가 스레드의 의도대로 저장되지 않고 스레드간 충돌이 발생해 의도치 않은 값으로 저장될 것이다. 따라서 여러 스레드가 공유데이터를 사용할 때는 스레드 간 순서대로 실행시켜야 데이터가 정상적으로 메서드 내용에 맞게 저장된다.
예시로 화장실을 들 수 있는데 집에 화장실이 하나인데 여러 사람이 사용하려고해도 한명만 들어가서 이용해야 하는 것처럼 스레드의 동기화의 필요성도 같은 개념으로 생각하면 된다.
스레드 동기화 영역지정 문법
스레드 내 요소 앞에 synchronized를 붙혀주어 지정한다.
1. 메소드 전체를 영역으로 지정
synchronized void 함수이름(){...}
위 함수가 실행되는 동안은 다른 스레드로 JVM이 진입 불가함.
2. 코드 블록을 영역으로 지정
synchronized(this){...}
위 코드로 감싸진 코드 블록을 JVM이 읽을때 다른 스레드로 진입 불가함.
스레드 상태 메서드를 통한 동기화 제어
스레드 상태메서드인 wait()와 notify(), notifyAll()을 이용하면 synchronized로 이미 동기화된 스레드를 제어할 수 있다.
-
wait()
다른 스레드가 이 객체의 notify()를 불러줄 때까지 대기한다. -
notify()
오직 한개의 스레드만 깨워 Runnable 상태로 만든다. -
notifyAll()
대기 중인 모든 스레드를 깨우고 모두 Runnable 상태로 만든다.
대표적인 예시가 동영상 스트리밍이다.
네트워크 오류로 영상의 송출이 느려지면 영상버퍼가 비게되고 재생간 오류가 생길 것이다. 이럴때 재생스레드는 wait로 대기상태로 바뀌며 버퍼가 다 찰때까지 기다렸다가 다 차면 입력스레드가 재생스레드를 notify()로 깨워서 영상을 처리해준다.
반대의 경우도 있다. 네트워크가 빨라 재생스레드 속도가 버퍼의 영상을 다 실행기키도 전에 입력스레드가 실행되면 오류가 발생하므로 영상버퍼를 재생스레드가 다 처리할때까지 입력스레드를 wait상태로 바꾸고 다 처리하면 notify()로 버퍼를 다시 영상으로 채워준다.
Author And Source
이 문제에 관하여(<TIL> java_Thread), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@padd60/TIL-javaThread저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)