[스터디할래] whitesheep #10 쓰레드

금주의 공부할 내용 !

  • Thread 클래스와 Runnable 인터페이스
  • 쓰레드의 상태
  • 쓰레드의 우선순위
  • Main 쓰레드
  • 동기화
  • 데드락

Thread 클래스와 Runnable 인터페이스

  • 기본적으로 구현은 run() 메서드를 오버라이드한다

  • 실행부에서 start()메서드를 사용해서 호출해야 쓰레드가 별도의 실행 공간에서 실행된다

Thread 클래스를 상속

class MyThread extends Thread {
		@Override
		public void run() {
			System.out.println("hello my thread");
		}
	}

실행부

MyThread myThread = new MyThread();
myThread.start();

Runnable 인터페이스를 구현

static private class MyRunnableImpl implements Runnable {
		@Override
		public void run() {
			System.out.println("hello runnable");
		}
	}

실행부

MyRunnableImpl runnable = new MyRunnableImpl();
Thread th = new Thread(runnable);
th.start();

만일 start가 아닌 run 메서드를 이용한다면??

쓰레드로 실행이 되지 않는다

class MyThread extends Thread {
	@Override
	public void run() {
		sleep(300);
		System.out.println(getName() + " hello my thread");
	}

	private void sleep(int millis) {
		try {
			Thread.sleep(millis);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
}

위와 같이 쓰레드에 딜레이를 걸어 놓는다

그리고 run메서드를 통해서 실행한다

MyThread[] myThread = new MyThread[10];
for (int i = 0; i <10; i++) {
	myThread[i] = new MyThread();
	myThread[i].run(); // 이곳 !!
}

그렇게 되면 main 메서드에 순차적으로 0.3초씩 메세지가 쌓이는 것이 보인다

그리고 start메서드를 통해서 실행하면 0.3초 뒤 한번에 메세지가 일괄 출력된다

run메서드는 쓰레드를 실행시키는 것이 아니라 단순히 클래스에 선언된 run메서드를 호출하는 것이다

반면 start()는 쓰레드가 작업을 실행하는데 필요한 call stack을 생성한 다음에

run()을 호출해서 방금 생성한 stack에 run()을 실행한다

쓰레드의 상태

상태의미관련 메서드
NEW쓰레드 인스턴스를 생성하였지만 아직 실행되지 않음new
RUNNABLE실행 중start()
BLOCKED실행 중지, 즉 monitor lock이 풀리기를 기다림 
WAITING대기 중sleep(초) 혹은 wait(초)
TIMED_WAITING특정 시간만큼 대기 중sleep() 혹은 wait()
TERMINATED종료된 상태join() 이후

** 비고 WAITING, TIMED_WAITING 는 Thread.sleep() 메서드나 monitor객체의 wait 메서드로 대기할 때 나오는 상태이다

쓰레드의 우선 순위

  • 자바의 신 내용을 기준으로 작성해보았다

  • 우선순위의 기본값은 5이다 (getPriority())

  • 되도록 우선순위는 지정하지 않는것이 좋다고 한다

  • 그래도 굳이 지정해야겠다면 Thread 클래스의 상수를 이용하자 (아래 그림)

image

데몬 쓰레드

  • 해당 쓰레드를 실행하는 컨텍스트가 종료되면 보통 쓰레드는 종료되지 않고 실행된다
    • 예를들어 main() 는 종료되었지만 쓰레드는 살아 있는 것
  • 이때 setDaemon(true) 을 지정하여 같이 종료를 시킬 수 있다

Main 쓰레드

- main함수도 쓰레드이다 !!

동기화

어떤 Target 객체가 있고 이 객체가 상태를 가지고 있을 때

이 객체를 여러 쓰레드가 사용할 떄 동기화 문제가 발생할 수 있다

이것을 해결하기 위한 방법 중 하나로 synchronized 예약어를 이용할 수 있다

synchronized

  • 사용 방법은 크게 두가지가 있다
    • 메서드 자체를 synchronized로 선언하는 방법 (synchronized methods)
    • 메서드 내 특정 문장만 감싸는 방법 (synchronized statement)

싱글턴에서의 동기화 문제

필자가 작성한 글에서도 확인해볼 수 있다 .. ㅎㅎ

https://progress0407.github.io/backend/2021/12/02/%EC%9E%90%EB%B0%94_%EB%94%94%EC%9E%90%EC%9D%B8%ED%8C%A8%ED%84%B4-6-Singleton.html

데드락

교착상태이다

  • 특정 조건이 갖추어지면 락이 걸린다

참고

  • resumeQ, stopO, suspend() 는 쓰레드를 교착상태 (dead-lock)로 만들기 쉽기 때문에 deprecated되었다.




© 2020.12. by 따라쟁이

Powered by philz