[Java] 다중 스레드

chael_lo·2021년 5월 13일
0

Java

목록 보기
20/52

다중 스레드

개발자가 직접 스레드를 생성하여 여러 명령이 동시에 실행되도록 프로그램 작성하는 것이다.

개발자가 스레드를 생성하여 명령 실행 👉 프로그램의 모든 스레드가 소멸되면 프로그램이 종료

다중 스레드 프로그램

  • GUI 프로그램
  • 웹 프로그램

다중스레드 프로그램 작성

JVM에 의해 main 스레드는 자동 생성 되며,
main 스레드 외 다른 스레드를 생성하여 명령 실행한다.

Thread 클래스를 상속받는 스레드를 생성

Thread 클래스를 상속받은 자식 클래스를 만들고 run() 메소드 오버라이드 선언한다.

//자식 클래스
public class MultiThreadOne extends Thread {
	@Override
	public void run() {
		//새로운 스레드로 실행될 명령 작성
		for(char i='A';i<='Z';i++) {
			System.out.print(i);
		}
	}
}

Thread 클래스를 상속받은 스레드 실행 순서

Thread 인스턴스로 start() 메소드를 호출하여 스레드 생성한다.
생성된 스레드는 자동으로 run() 메소드의 명령 실행한다.
Thread 클래스를 상속받은 자식 클래스로 인스턴스 생성한다.
자식 클래스의 생성자로 인스턴스를 생성하여 부모(Thread) 인스턴스가 먼저 생성된다.
부모(Thread) 인스턴스의 start() 메소드를 호출하여 스레드 생성한다.
생성된 스레드는 자식 클래스에서 오버라이드 선언된 run() 명령 실행된다.

public class MultiThreadApp {
	//main 메소드에서 전달되는 모든 예외는 JVM이 자동으로 예외 처리
    	//JVM에 의해 main 스레드 자동 생성
	public static void main(String[] args) throws InterruptedException {

		new MultiThreadOne().start();
		
		for(char i='0'; i<='9'; i++) {
			System.out.print(i);
			Thread.sleep(500);
		}
	}
}

Runnable 인터페이스를 상속받아 스레드 생성

Thread 클래스를 상속 받지 못할 경우(이미 다른 클래스를 상속 받고 있을 때) 사용한다.
Runnable 인터페이스를 상속받는 자식 클래스 만들고, 자식 클래스에서 run 메소드를 오버라이드 선언한다.

//자식 클래스
public class MultiThreadTwo implements Runnable{
	@Override
	public void run() {
		for(char i='a';i<='z';i++) {
			System.out.print(i);
		}
	}

}

Runnable 인터페이스를 상속받은 스레드 실행 순서

Runnable 인터페이스를 상속받은 클래스로 인스턴스 생성한다.
Runnable 인스턴스를 전달받아 Thread 인스턴스 생성하는 생성자 호출하며, 이는 run() 메소드가 오버라이드 선언되는 것과 같은 효과가 생긴다.
Thread 인스턴스로 start() 메소드를 호출한다.
새로운 스레드를 생성하여 run() 명령 실행한다.

//참조 변수를 만드는 경우
Thread thread = new Thread(multiThreadTwo);
thread.start();

//한번만 호출 가능해서 변수를 선언하지 않아도 된다.
//참조 변수를 만들지 않는 경우 -> 가독성 증가
new Thread(new MultiThreadTwo()).start();

Thread 클래스의 메소드

  • start: 스레드를 생성하여 run() 메소드에 작성된 명령을 실행하는 메소드
  • stop: 스레드를 강제로 소멸시키는 메소드
  • suspend: 스레드를 일시 중지 시키는 메소드
  • resume: suspend 메소드로 중지된 스레드를 실행하는 메소드
  • sleep: 원하는 시간(ms)동안 스레드를 일시 중지하는 메소드

Thread 우선 순위 변경

우선순위 기본 값: 5
Thread에 우선순위를 새롭게 지정할 수 있다.

PriorityOne one = new PriorityOne();
PriorityTwo two = new PriorityTwo();
		
one.setPriority(Thread.MIN_PRIORITY);//상수값: 1, 우선순위가 낮음
two.setPriority(Thread.MAX_PRIORITY);//상수값: 10, 우선순위가 높음

다중 스레드의 문제점

동일한 run() 메소드의 명령을 실행하는 다수의 스레드에서 인스턴스 필드값 변경 관련 동일 메소드 호출시 조작에 대한 잘못된 결과를 반환 받을 수 있다.

@Override
public void run() {
	//다수의 스레드에서 인스턴스 필드값 변경 관련 동일 메소드 호출
       명령...
}

다중 스레드의 문제점의 해결방법

스레드 동기화(Thread synchronized)

스레드의 메소드 호출에 대한 스레드 일시 중지 기능이다.
다수의 스레드가 인스턴스 필드값 변경 관련 동일 메소드를 호출할 경우
먼저 호출 요청한 스레드에 대한 처리 결과가 제공될 때까지 다른 스레드의 메소드 호출에 대한 명령 처리를 일시 중지(Method Lock)한다.

스레드 동기화 방법

  1. 동기화 메소드(synchronized Method): 인스턴스 필드값 변경 메소드에 대한 동기화 처리한다.
    synchronized: 스레드에 대한 동기화 처리 메소드로 설정하기 위한 지정자
public synchronized void deposit(String name, int amount){//입금 처리 메소드
	balance+=amount;
	System.out.println("[입금]"+name+"님이 "+amount+"원 입금하여 잔액은 "+balance+"원입니다.");
}

2.동기화 영역(synchronized Block): 인스턴스를 전달받아 인스턴스의 모든 메소드를 동기화 처리하여 호출한다.

@Override
public void run() {
//account가 들어간 모든 메소드가 동기화 처리
  synchronized (account) {
     account.withDraw(userName, 2000);
  }
}
profile
천천히 꾸준히

0개의 댓글