JAVA Thread
Thread
동시에 실행해야 하는 일이 있을 때 스레드를 사용함
메인스레드 | │ │ │ │ │ │ ↓ | 사용자 생성스레드 | │ │ │ │ │ │ ↓ | 사용자 생성스레드 | |
클래스 | 클래스 | 클래스 | |||
스택 | 스택 | 스택 | |||
힙 | 힙 | 힙 | |||
스레드끼리는 클래스 및 힙영역의 데이터를 주고받을 수 있음
단. 스택영역의 데이터는 주고받을 수 없음
스레드끼리는 데이터를 주고받는 과정에서 오류가 발생할 수 있으며,
이는 스레드 동기화를 통하여 해결하여야 한다.
Thread ct = Thread.currentThread();
String tName = ct.getName();
System.out.println(tName);
스레드ct에 현재 사용중인 스레드를 받아와, tName에 그 스레드의 이름값을 투입하여 출력함.
스레드의 구현
스레드 클래스 생성 - 스레드 객체 생성 - 스레드 생성
스레드 생성 방법
1. Thread 클래스를 상속(extends)하는 클래스를 이용
ㄴ 소스 - 오버라이드/임플리먼츠 메서드 - run()을 오버라이드하여 사용
ㄴ 스레드클래스명 변수명 = new 스레드클래스명
ㄴ 변수명.start(); -현재 시점에서 스레드가 생성됨
2. Runnable인터페이스를 구현(implements)하는 클래스를 이용
ㄴ 스레드클래스명 러너블변수명 = new 스레드클래스명
ㄴ Thread 변수명 = new Thread(러너블변수명);
스레드의 생애
1. 스레드 생성(start() 호출)
2. runnable상태
3. running 상태
ㄴ Thread.sleep();등을 만나면 Blocked 상태로 변경
ㄴ 블락상태의 스레드는 블락이 끝난 후 러너블상태로 돌아감
4. 스레드 종료(Dead상태)
스레드 동기화
1. join()메서드
ㄴ join()메서드를 호출한 스레드의 작업이 끝날때까지 현재의 스레드는 작업을 멈춘다.
ㄴ 메인스레드에서 t1.join();으로 호출할 시, t1스레드의 작업이 종료될때까지 메인스레드의 작업이 멈춤
ㄴ
메인스레드 이외에의 스레드 동기화 방법 ex) 스레드 a가 끝날때까지 스레드 b를 멈춰라! 멈춰야 할 스레드 bbbbbbbbbbbaaaabbbbbbbbbbbbb인 타임라인이 그려짐. 이 경우 스레드b에서 작업을 시행해야 함. 스레드 b에서 a.join();을 선언함 a.join();을 선언하기 위해서 인스턴스변수 Thread a;를 선언 Thread a;를 선언하고, 사용하기 위해서 사용자 생성자(컨스트럭터 유징필드)를 선언해줌. 사용자 생성자를 선언하였음. 해당 사용자 생성자를 사용하였으니 스레드 b에 a값을 넣어줌 ChildThread3 rt3 = new ChildThread3(a); |
메인 스레드 package kr.co.joeun; public class MainEx { ChildThread at1 = new ChildThread(); //스레드 1을 만듦 //스레드1은 스레드 상속 ChildThread3 rt3 = new ChildThread3(at1); //스레드 3을 만들 때 스레드 1을 넣어줌 //스레드3은 임플리먼츠 러너블 } } |
멈추어야 할 스레드 package kr.co.joeun; public class ChildThread3 implements Runnable {
public ChildThread3(Thread t1) {
@Override } //t1.join의 트라이캐치 } |
상기 표의 설명
1. 스레드 at3의 생성자에 요구되는 값 t1
2. 스레드 at3의 변수 t1에 메인클래스에서 스레드 at1값을 넣어줌.
3. 스레드 at3이 실행되는 중 at1에서 (스레드3의 변수)t1을 거친 스레드at1이 join();을 요청함.
4. 스레드 at3은 잠시 중지되고 스레드at1이 실행됨
데이터의 동기화(하나의 작업을 입/출력까지 하나로 묶어서 처리하는 것)를 임계영역별로 나누어 동기화 처리
해당 동기화 처리는
메서드를 syncronized 처리함.
public syncronized void me1(){}
동기화 블럭의 사용법
메서드 내부의 영역에 서라운드위드 - 싱크로나이즈드 - mutax를 this로 수정, 또는 Object obj = new Object(); 등의 선언 이후 obj를 넣어서 동기화 블럭의 열쇠로 활용
public void plusNum(int add) {
synchronized (this) {
num += add;
}
}
등의 방식으로 사용
접근순서에 대한 동기화
if문, try~catch, 동기화 블록, notify(); , waiting(); 등의 문법을 사용
if문을 통하여 wait();를 실행할 지 정하고, wait문은 싱크로나이즈드로 감싸줌(서라운드 위드-싱크로나이즈드)
notify();가 실행되면 wait();문에 의한 대기를 끝냄. notify문 역시 싱크로나이즈드로 감싸줌.
작가가 글을 올리면 독자가 읽는다!
일 때, 독자가 먼저 글을 읽기 위해 접근할 경우 wait문으로 정지시키고
작가가 글을 올리면 notify문으로 독자의 wait를 해제시켜 주는 형식.
익명으로 만든 스레드
new Thread(new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
System.out.println("익명으로 만든 스레드");
}
}).start();