Thread (1)
- Thread : 프로세스 하나의 작업단위이다. 멀티 스레드는 2개 이상의 작업이다.
*Process : 하나의 프로그램을 말한다. OS에서 두 개 이상의 프로그램이 실행되면 멀티 태스킹이라 한다.
- 스레드 스케줄링: 스레드를 멀티 작업을 위해 하나의 코어에서 다수의 스레드가 번갈아가며 실행하는 기법, 즉, 다수의 스레드를 어떤 순서로 실행할 것인가를 정하는 작업
1. 특징
- 실행 대기 상태: 아직 스케줄링이 되지 않아서 실행을 기다리는 상태
- 실행 상태: 실행 대기 상태에 있는 스레드 중에서 스레드 스케줄링으로 선택된 스레드가 CPU를 점유하고 run()메소드를 실행하는 상태
- 스레드 객체를 생성하고, start() 메소드를 호출하면 스레드가 실행되는 것처럼 보이지만 사실은 실행대기 상태가 됨
- 실행 대기 상태에 있는 스레드 중에서 스레드 스케줄링으로 선택된 스레드만이 실행 상태가 됨
- 실행 상태의 스레드는 완료되면, 스레드 스케줄링에 의해 다시 실행 대기 상태로 돌아갈 수 있음
- 실행 대기 상태에 있는 다른 스레드가 선택되어 실행 상태가 됩니다.
2. 스레드 스케쥴링
- 종료 상태: run() 메소드가 종료되어 더 이상 실행할 코드가 없어져 스레드의 실행을 멈추는 것
- 일시 정지 상태: 스레드가 실행할 수 없는 상태로 WAITING, TIMED_WAITING, BLOCKED의 세 가지 상태가 존재함
- 경우에 따라 스레드는 실행 상태에서 실행 대기 상태로 가지 않고, 일시 정지 상태로 가기도 함
- start() 메소드를 사용하면 모든 작업이 섞여서 실행 됨 (이 것은 run()을 직접 호출하는게 아니라 시스템 호출이라고 함)
이렇게 스레드는 실행 대기 상태와 실행 상태를 번갈아가면서 run() 메소드를 실행. 실행 상태에서 run() 메소드가 종료되면, 더 이상 실행할 코드가 없기 때문에 스레드의 실행이 멈추는 종료 상태로 전환
▶ 알파벳과 10의 배수 출력문제
public class Ex01 {
public static void main(String[] args) {
Digit01 digit = new Digit01();
//digit.run(); //run을 재정의하고 start를해야함
digit.start();
for(char i=1;i<=50;i++) {
System.out.print("main fuction" + "\t");
}
Alphabet01 alphabet = new Alphabet01();
alphabet.start();
}
}
public class Alphabet01 extends Thread{
public void run() { //call back 함수
for(char i='A';i<='z';i++) {
System.out.print(i + "\t");
if(i == 'Z') System.out.println();
}
System.out.println();
}
}
public class Digit01 extends Thread{ //스레드를 사용하려면 상속받아야함
public void run() {
for(char i=1;i<=100;i++) {
System.out.print(i + "\t");
if(i % 10 == 0) System.out.println();
}
System.out.println(); //10의 배수마다 줄바꿈
}
}
* 멀티 스레드의 예시: 워드 작업 중 저장, 네이트온에서 채팅하면서 음악듣기, 10초안에 입력없으면 창 종료 등등..
▶ 입력 스레드 문제
public class Ex02 {
public static void main(String[] args) {
SubThread st = new SubThread();
st.start();
InputThread it = new InputThread();
it.start();
}
}
public class InputThread extends Thread {
@Override
public void run() {
String input = JOptionPane.showInputDialog("10초안에 값을 입력하세요"); //외부에서 받는 건 다 스트링타입
if(input != null) {
SubThread.inputCheck=true;
System.out.println("입력하신 값은 " + input + "입니다." );
System.exit(0); // 스레드 모두 정상 종료 Terminated
}
}
}
public class SubThread extends Thread {
public static boolean inputCheck = false; //static이므로, 객체발생없이 inputCheck가 계속살아있을 수 있음
@Override
public void run() {
for(int i=10;i>0;i--) {
System.out.println(i);
if(inputCheck) return; //입력값이 있다면, 아래 실행안하고 빠져나감
try {
sleep(1000); // 1000ms = 1 second
} catch(InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("데이터가 입력되지 않았습니다."); //for를 다돌고 나와서
System.exit(0); // 스레드 모두 정상 종료 Terminated
}
}
* Runnable 인터페이스 구현와 사용자 임의 클래스 상속을 동시에 할 수 있다.
* Thread가 실행되면 '실행대기상태'로 가는데 이를 Runnable 상태라 한다. (아직 스케쥴링 안된 상태)
class AA { // 내가 만든 클래스
public void disp() {
System.out.println("hahahaha");
}
}
class Alphabet02 extends AA implements Runnable{
@Override
public void run() {
for(char i='A';i<='z';i++) {
System.out.print(i + "\t");
try {
Thread.sleep(1000);
} catch(InterruptedException e) {
e.printStackTrace();
}
}
System.out.println();
}
}
class Digit02 extends Thread {
@Override
public void run() {
for(int i=1;i<=10;i++) {
System.out.print(i + "\t");
try {
Thread.sleep(1000);
} catch(InterruptedException e) {
e.printStackTrace();
}
}
System.out.println();
}
}
public class Ex03 {
public static void main(String[] args) {
Digit02 digit= new Digit02();
digit.start();
Alphabet02 alpha = new Alphabet02();
Thread thread = new Thread(alpha);
thread.start();
}
}