쓰레드 (thread) - 작업자,작업 스케줄러에 의해 시간을 배정 받아 CPU에서 작업할 수 있는 단위 -> 동시 실행이 가능하다.
**APP**을 만든다고 가정하면
ex) 프로세스(회사) - 스레드(기획자) => 기획서
- 스레드(디자이너) => 디자인
- 스레드(개발자) => 코딩
만약 혼자 APP을 만들 경우, 단계에 맞게 하나씩 차례차례 처리해야 되므로 시간이 많이 걸리지만 // 여러 사람이 각 단계에 맞는 일(작업)을 부여받아 동시에 맡은 작업을 처리하므로 시간을 단축할 수 있다.
하지만 쓰레드가 특정 변수를 참조할 때 생기는 동시성의 문제가 생기기 때문에 동기화 처리를 통해 안전하게 처리가 가능하다.
프로세스에 할당된 메모리 영역에서 실행 / 프로세스에 할당된 시스템 리소스 공유
자바에서 스레드를 사용하는 이유는 비동기적 작동 방식(독립스레드)에 대한 개념이 없음
• 프로그래밍 방식이 자바에서는 사용이 가능하지 않음
• 비동기적 작동 방식 구현 : ‘스레딩 기술의 사용 방법’ 숙지
– 자바가 실행되는 기반인 자바가상머신(Java virtual machine, 이하 JVM) 자체가 하나의 ***'프로세스'***임
• 언어적 차원 : 스레드의 동기화 지원 가능
• 다중 스레드 프로그램을 쉽고 명료하게 만들 수 있음
-다중 쓰레드
– 동기화 메소드들을 기본적인 키워드로 제공함으로써 자바 언어 수준에서 다중 쓰레드 지원
– 자바 API : 쓰레드를 지원해주기 위한 쓰레드 클래스 존재
– 자바 런 타임 시스템 : 모니터와 조건 잠금 함수 제공
– 시분할 기법(Time-Shared)
• 멀티태스킹 및 멀티스레드를 가능하게 하는 기법
• 아주 짧은 시간 간격을 두고 여러 개의 프로그램을 전환하면서 실행
• 빠른 속도 때문에 두 개 이상의 프로그램이 동시에 실행되는 처럼 느껴짐
• 프로그램의 실행을 전환하는 것은 OS가 담당함
– 다중 스레드의 이점
• 자원을 효율적으로 사용할 수 있음
• 사용자에 대한 응답성이 향상됨
• 작업이 분리되어 코드가 간결함
– 다중 스레드의 단점
• 동기화에 주의해야 함
• 교착상태가 발생하지 않도록 주의해야 함
• 각 스레드가 효율적으로 고르게 실행될 수 있게 해야 함
쓰레드의 구현과 실행
1.Thread 클래스를 상속 - 별도의 쓰레드 생성을 위해서는 별도의 쓰레드 클래스를 정의해야 한다.
2.Runnable interfaces를 구현 - 다중 상속을 위해서
-Runnable 인터페이스를 구현하는 클래스의 인스턴스를 대상으로 Thread 클래스의 인스터를 생성한다. 상속할 클래스가 존재할 때 유용하게 사용됨
start()
run()
join()
sleep() -> 기본값은 1/1000s[초]
Runnable 상태의 쓰레드만이 스케줄러에 의해 스케줄링이 가능하다.
그리고 앞서 보인 sleep, join 메소드의 호출로 인해서 쓰레드는 Blocked 상태가 된다.
한번 종료된 쓰레드는 다시 Runnable 상태가 될 수 없지만,
Blocked 상태의 쓰레드는 조건이 성립되면 다시 Runnable 상태가 된다.
모든 쓰레드는 스택을 제외한 메소드 영역과 힙을 공유한다.
따라서 이 두 영역을 통해서 데이터를 주고 받을 수 있다.
스택은 쓰레드 별로 독립적일 수 밖에 없는 이유는, 쓰레드의 실행이 메소드의 호출을 통해서 이뤄지고,
메소드의 호출을 위해서 사용되는 메모리 공간이 스택이기 때문이다.
***************************************************동기화(synchronized)*************************************************
-한 번에 하나의 쓰레드만 객체에 접근할 수 있도록 객체에 락(lock)을 걸어서 데이터의 일관성을 유지하는 것
동기화처리 - 하나의 스레드가 조작하고 있는 변수를 다른 스레드가 조작하지 못하도록 동기화가 필요함.
동기화에 사용되는 인스턴스는 하나이며, 이 인스턴스에는 하나의 열쇠만이 존재한다.
쓰레드를 이용한 예제 |
package ex.th;
import javax.swing.JOptionPane;
public class HighLowMain {
public static boolean check = false;
public static void main(String[] args) {
Count ct = new Count();
CheckNumber num = new CheckNumber();
// 4.10초 이전에 맞추면 미션 성공, 10초가 지나면 프로그램 종료하는 흐름으로 만드리
num.start();
ct.start();
}
}
// 3.10초 카운팅은 스레드를 이용해서 처리
class Count extends Thread {
@Override // 쓰레드 클래스를 상속시 run() 메서드를 오버라이딩, 구현부를 작성해준다.
public void run() {
for (int i = 10; i > 0; i--) {
// 10초이내에 정답입력시
if (HighLowMain.check) {
System.out.println("미션 성공입니다.");
return;
}
System.out.println(i);
try {
// 1초 간격
sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("입력시간 초과입니다.");
System.out.println("10초이내에 정답을 못 맞췄으므로 프로그램이 종료됩니다.");
System.exit(0);
}
}
class CheckNumber extends Thread {
@Override
public void run() {
// 1.1~100 사이의 랜덤 숫자를 설정합니다.
int random = (int) (Math.random() * 100) + 1;
System.out.println(random);
// 2.사용자에게 숫자를 입력 받고, 랜덤 숫자와 비교하고, 높은 숫자인지 낮은 숫자인지 출력
while (!HighLowMain.check) {
String answer = JOptionPane.showInputDialog("숫자를 입력해주세요: ");
int num = Integer.parseInt(answer);
int result = num - random;
if (result > 0) {
System.out.println("낮은 숫자를 입력해주세요.");
}else if(result < 0) {
System.out.println("높은 숫자를 입력해주세요.");
}else {
System.out.println("정답입니다.");
HighLowMain.check =true;
return;
}
}
}
}