반응형
01. 스레드(Thread)의 개념
- 프로그램에서 명령을 실행하기 위한 최소의 작업 단위 - 프로그램 흐름
- 하나의 스레드 = 하나의 코드 실행 흐름
- 프로세스(Process) : 메모리에 저장되어 중앙처리장치(CPU)에 의해 실행되는 명령 프로그램
- [1개 프로세스 내 2개 스레드가 있다] = 2개의 코드 실행 흐름을 가진 프로그램
🎩단일 스레드 프로그램
- JVM에 의해 생성된 main 스레드를 이용하여 main() 메소드의 명령 실행
- main 메소드가 종료되면 main 스레드는 자동 소멸 - 프로그램 종료
🎩다중 스레드 프로그램
- 프로그램 개발자가 스레드를 직접 생성하여 여러 명령을 동시에 실행되도록 만든 프로그램
- 프로그램의 모든 스레드가 소멸되면 프로그램 종료
- 즉, 메인스레드가 끝난다고 해서 프로그램이 종료되지는 않음
- ex. GUI프로그램, Web프로그램 등은 다중 스레드 프로그램으로 작성
02. Thread클래스
- 스레드 관련 정보를 저장하고 스레드 관련 기능을 메소드로 제공하는 클래스
- 중요한 것은 스레드객체를 제어하는 것보다 스레드를 만드는 것이 더 중요하다!!!!
🎩다중스레드를 사용해야 하는 이유
- CPU가 여러개 있지 않은 이상 명령은 동시 처리 불가능
- PC에 CPU는 한개
- 그래서 스레드를 여러개 만드는 것
- 스레드 하나가 아닌 여러개 있다면 명령이 동시에 처리하는 것처럼 보임
- 대다수의 프로그램은 스레드 여러개로 만듦
- 콘솔프로그램은 단일 스레드 가능
- GUI프로그램은 무조건 다중 스레드..
- 메인 스레드 말고(JVM이 만들어준) , 우리가 직접 스레드를 만들어 사용해야함
- 왜? 명령들이 동시에 처리될 수 있도록 하기 위해!!!
03. 단일스레드 프로그램
- JVM에 의해 생성된 main 스레드를 이용하여 main() 메소드의 명령 실행
- main 메소드가 종료되면 main 스레드는 자동 소멸 - 프로그램 종료
1. 🎩SingleThreadApp 프로그램
package xyz.itwill.thread;
//스레드(Thread) : 프로그램(프로세스)에서 명령을 실행하기 위한 최소의 작업 단위 - 프로그램 흐름
//프로세스(Process) : 메모리에 저장되어 중앙처리장치(CPU)에 의해 실행되는 명령
//단일 스레드 프로그램
// => JVM에 의해 생성된 main 스레드를 이용하여 main() 메소드의 명령 실행
// => main() 메소드가 종료되면 main 스레드는 자동 소멸 - 프로그램 종료
public class SingleThreadApp {
//메인메소드
public static void main(String[] args) {
/*
System.out.println("SingleThreadApp 클래스의 main() 메소드 시작");
//Thread 클래스 : 스레드 관련 정보를 저장하고 스레드 관련 기능을 메소드로 제공하는 클래스
//Thread.currentThread() : 현재 사용중인 스레드에 대한 Thread 객체를 반환하는 메소드
//Thread.getName() : Thread 객체에 저장된 스레드의 이름(식별자)을 반환하는 메소드
System.out.println("["+Thread.currentThread().getName()"] 스레드에 의해 main() 메소드의 명령 실행");
//🍯 메소드를 한번만 호출한다면? 참조변수 생성해 객체를 저장하지 않는다
//객체를 사용하여 메소드를 호출한 경우 스레드가 클래스의 메소드로 이동하여 명령 실행
// => 메소드의 명령을 모두 실행한 뒤 다시 되돌아와 나머지 명령 실행
new SingleThread().display();//객체를 생성한 후 메소드 호출
System.out.println("SingleThreadApp 클래스의 main() 메소드 종료");
*/
//SingleThreadApp 클래스의 main() 메소드 시작
//[main] 스레드에 의해 main() 메소드의 명령 실행
//SingleThread 클래스의 display() 메소드 시작
//[main] 스레드에 의해 display() 메소드의 명령 실행
//SingleThread 클래스의 display() 메소드 종료
//SingleThreadApp 클래스의 main() 메소드 종료
new SingleThread().display();
for(char i='0';i<='9';i++) {
System.out.print(i);
}
//ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789
}
}
2. 🎩SingleThread 클래스
package xyz.itwill.thread;
public class SingleThread {
public void display() {
/*
System.out.println("SingleThread 클래스의 display() 메소드 시작");
//Thread.currentThread.getName() : 현재 사용중인 스레드에 대한 Thread 객체에 저장된 스레드의 이름(식별자)을 반환
System.out.println("["+Thread.currentThread().getName()"] 스레드에 의해 display() 메소드의 명령 실행");
System.out.println("SingleThread 클래스의 display() 메소드 종료");
*/
for(char i='A';i<='Z';i++) {
System.out.print(i);
}
}
}
04. 다중스레드 프로그램
- 프로그램 개발자가 스레드를 직접 생성하여 여러 명령을 동시에 실행되도록 만든 프로그램
- 메인스레드가 끝나도 프로그램이 종료되지 않음
- 프로그램의 모든 스레드가 소멸되어야 프로그램 종료
- 즉, 메인스레드가 끝난다고 해서 프로그램이 종료되지는 않음
- ex. GUI프로그램, Web프로그램 등은 다중 스레드 프로그램으로 작성
1. 🎩MultiThreadApp 프로그램
- 다중 스레드로 프로그램(main, 스레드1,2,3)
package xyz.itwill.thread;
//🎩다중 스레드 프로그램
// => 프로그램 개발자가 스레드를 직접 생성하여 여러 명령을 동시에 실행되도록 만든 프로그램
// => 프로그램의 모든 스레드가 소멸되면 프로그램 종료
// => GUI 프로그램, Web 프로그램 등은 다중 스레드 프로그램으로 작성
//🎩프로그램 개발자가 새로운 스레드를 생성하여 명령을 실행하는 방법-1
//step1.
// => Thread 클래스를 상속받은 자식클래스 작성
//step2.
// => Thread 클래스를 상속받은 자식클래스에 run() 메소드를 오버라이드 선언
// => run() 메소드에는 프로그램 개발자에 의해 생성된 스레드가 실행할 명령 작성
//step3.
// => Thread 클래스를 상속받은 자식클래스로 객체 생성 - Thread 객체 생성
// => 자식클래스로 객체를 생성하면 부모객체인 Thread객체가 먼저 생성된다
//step4.
// => 자식클래스의 객체로 start() 메소드 호출 - Thread 객체의 start() 메소드 호출
// => Thread 객체로 새로운 스레드를 만들어 자식클래스에 오버라이드 선언된 run() 메소드의 명령 실행
// => 실제 Thread 객체의 start 메소드가 호출됨 (부모객체 간접 호출)
//🎩프로그램 개발자가 새로운 스레드를 생성하여 명령을 실행하는 방법-2
//step1.
// => Runnable 인터페이스를 상속받은 자식클래스 작성
// => 자식클래스가 다른 클래스를 상속받아 Thread 클래스를 상속받지 못할 경우 사용하는 방법
//step2.
// => Runnable 인터페이스를 상속받은 자식클래스에 run() 메소드를 오버라이드 선언
// => run() 메소드에는 프로그램 개발자에 의해 생성된 스레드가 실행할 명령 작성
//step3.
// => 생성자 매개변수에 Runnable 인터페이스를 상속받은 자식클래스의 객체를 전달받아 생성 - Thread 객체 생성
//step4.
// => Thread 객체로 start() 메소드 호출 - Thread 객체의 start() 메소드 호출
// => Thread 객체로 새로운 스레드를 만들어 Runnable 인터페이스를 상속받은 자식클래스의 오버라이드 선언된 run() 메소드에 명령 실행
public class MultiThreadApp {
//main() 메소드에 의해 전달되는 모든 예외는 JVM에 의해 자동으로 예외 처리
public static void main(String[] args) throws InterruptedException {
//JVM에 의해 main 스레드가 생성되어 main() 메소드의 명령 실행 - JVM은 main() 메소드의 명령만!!! 실행
//스레드의 존재가치없는 생성방법
/*
//Thread 객체를 생성하여 start() 메소드 호출
// => 새로운 스레드가 만들어지고 Thread 클래스의 run() 메소드를 호출하여 명령 실행
// => Thread 클래스의 run() 메소드에는 명령 미존재
//=> 즉, 스레드가 생성은 되지만, 문제는 실행할 명령이 없어서 스레드 생성해도 아무런 의미가 없음
Thread thread=new Thread();
thread.start();
*/
//🎩프로그램 개발자가 새로운 스레드를 생성하여 명령을 실행하는 방법-1
/*
//방법1. 💚객체 생성해 참조변수에 저장
MultiThreadOne one=new MultiThreadOne();
//Thread.start() : Thread 객체로 새로운 스레드를 생성하여 run() 메소드를 호출하여 실행하는 메소드
one.start(); //스레드1
//Thread 객체는 start() 메소드로 하나의 스레드만 생성하여 명령 실행 가능 - Thread 객체로 start() 메소드를 여러번 호출할 경우 IllegalThreadStateException 발생
// => 다중 스레드 프로그램에서 예외가 발생된 경우 예외가 발생된 스레드만 자동 소멸
//one.start(); //스레드1과 동일한 스레드 호출명령이기 때문에 error
*/
// => Thread클래스의 다양한 메소드들이 있지만, 그 중 start()메소드 한번만 호출할 것이기 때문에 객체를 생성 후 바로 메소드 호출해보자!
// => Thread.stop()메소드는 Deprecated(비권장) - 직접소멸하면 원치않는 스레드까지 소멸될 수 있기 때문
//방법2. 💚객체만 생성하고 참조변수에 저장은 안함
//Thread 객체로 start() 메소드외 다른 메소드를 호출하지 않을 경우 참조변수를 사용하지 않고 객체를 생성하여 직접 start() 메소드 호출하는 것을 권장
// => 새로운 스레드가 생성되어 MultiThreadOne 클래스의 run() 메소드의 명령 실행
new MultiThreadOne().start(); //🎩스레드1
new MultiThreadOne().start(); //🎩스레드2
//주의)
//아래와 같은 메소드호출은 main메소드의 스레드로 명령 실행됨, 반드시 start()메소드를 사용해야 다른 스레드가 호출됨
//new MultiThreadOne().run(); //main메소드의 스레드로 run()메소드실행
//🎩프로그램 개발자가 새로운 스레드를 생성하여 명령을 실행하는 방법-2
// => 방법1. 이용해 새로운 스레드 생성
//Thread(Runnable target) : Runnable 인터페이스를 상속받은 자식클래스의 객체를 전달 받아 Thread 객체를 생성하는 생성자
// => Thread 객체의 run() 메소드를 오버라이드 선언하는 것과 같은 효과
new Thread(new MultiThreadTwo()).start(); //🎩스레드3
for(char i='0';i<='9';i++) {
System.out.print(i);
//Thread.sleep(long ms) : 현재 명령을 실행하는 스레드를 원하는 시간(ms)만큼 일시적으로 중지하는 메소드
// => InterruptedException 발생 : 일반 예외 - 예외처리를 하지 않으면 에러 발생
// => try-catch(예외처리)보다 main메소드에게 떠넘기면 JVM이 알아서 예외처리해줌(예외전달)
Thread.sleep(500);
}
}
}
2. 🎩MultiThreadOne 클래스
package xyz.itwill.thread;
//🎩프로그램 개발자가 새로운 스레드를 생성하여 명령을 실행하는 방법-1
public class MultiThreadOne extends Thread {
@Override
public void run() {
for(char i='A';i<='Z';i++) {
System.out.print(i);
try { //오버라이드 선언된 메소드 안 명령은 무조건 try-catch만 가능
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
3. 🎩MultiThreadTwo 클래스
package xyz.itwill.thread;
//🎩프로그램 개발자가 새로운 스레드를 생성하여 명령을 실행하는 방법-2
public class MultiThreadTwo implements Runnable {
@Override
public void run() {
for(char i='a';i<='z';i++) {
System.out.print(i);
try { //오버라이드 선언된 메소드 안 명령은 무조건 try-catch만 가능
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
반응형
'java > java.lang' 카테고리의 다른 글
[java/lang] 8. 입출금프로그램 (feat. 다중 스레드) (1) | 2024.06.17 |
---|---|
[java/lang] 6. Exception 클래스 (0) | 2024.06.16 |
[java/lang] 5. StringBuffer 클래스 (0) | 2024.06.15 |
[java/lang] 4. Wrapper 클래스 (1) | 2024.06.15 |
[java/lang] 3. String 클래스 (0) | 2024.06.14 |