2개 이상의 스세드를 사용하여 명령을 제공받아 실행
프로그램 개발자가 직접 스레드를 생성하여 다수의 스레드로 동시에 명령이 실행되는 프로그램
프로그램을 실행하는 모든 스레드가 소멸돼야만 프로그램 종료
GUI 프로그램 또는 Web 프로그램 등은 다중 스레드 프로그램으로 작성
Thread 클래스를 상속받은 자식클래스 선언 (내부클래스 권장)
Thread 클래스를 상속받은 자식클래스에서 무조건 run() 메소드를 오버라이딩 선언
=> run() 메소드에는 Thread 객체에 의해 생성된 새로운 스레드가 실행하기 위한 명령 작성
Thread 클래스를 상속받은 자식클래스의 생성자로 객체 생성 - Thread 객체
생성된 Thread 객체를 참조하여 Thread 클래스의 start() 메소드 호출
=> Thread 객체로 새로운 스레드가 생성되어 run() 메소드를 자동 호출해 명령 실행
=> 스레드로 run() 메소드의 명령을 모두 실행하면 스레드 자동 소멸
Runnable 인터페이스를 상속받은 자식클래스 선언
=> 자식클래스가 이미 다른 클래스를 상속받아 Thread 클래스를 상속받지 못하는 경우 사용
Runnable 인터페이스를 상속받은 자식클래스에서 무조건 run() 메소드를 오버라이딩 선언
=> run() 메소드에는 Thread 객쳉에 의해 생성된 새로운 스레드가 실행하기 위한 명령 작성
Runnable 인터페이스를 상속받은 자식클래스의 생성자로 객체 생성 - Runnable 객체
Thread 클래스 생성자의 매개변수에 Runnable 객체를 전달하여 Thread 객체 생성
=> 생성자 매개변수에 Runnable 객체를 전달하여 Thread 객체 생성
=> Runnable 인터페이스를 상속받은 자식클래스의 run() 메소드를 Thread 객체로 사용 가능
생성된 Thread 객체를 참조하여 Thread 클래스의 start() 메소드 호출
// 스레드를 생성하기 위해 선언된 클래스
public class MultiThreadOne extends Thread {
// 오버라이딩은 예외를 throws로 던질 수 없음
// 무조건 try catch로 처리해줘야됨
@Override
public void run() {
for(char i = 'A'; i <= 'Z'; i++){
System.out.print(i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class MultiThreadTwo implements Runnable{
@Override
public void run() {
for(char i = 'A'; i <= 'Z'; i++){
System.out.print(i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
public class MultiThreadApp {
public static void main(String[] args) throws InterruptedException {
/*
// 새로운 스레드를 생성하여 생성된 스레드로 원하는 명령 실행
// => Thread 클래스로 객체를 생성한 후 객체를 start() 메소드 호출 - 스레드가
// 생성되어 Thread 클래스의 run() 메소드를 자동 호출해 명령을 실행
// => Thread 클래스의 run() 메소드에는 실행될 명령이 없으므로 스레드가 생성된 후 바로 소멸
Thread thread = new Thread();
thread.start();
*/
/*
// 참조변수 생성
MultiThreadOne one = new MultiThreadOne();
// Thread.start(): Thread 객체를 사용하여 새로운 스레드를 생성하기 위한 메소드
// => 생성된 스레드는 Thread 객체를 참조하여 run() 메소드 자동 호출하여 명령 실행
one.start();
// 하나의 스레드 객체로 하나의 스레드만 생성 가능
// => Thread 객체로 start() 메소드를 다시 호출할 경우 IllegalThreadStateException 발생
// => 다중 스레드 프로그램에서 예외가 발생될 경우 예외가 발생된 스레드만 소멸
one.start();
*/
// Thread 객체를 참조하여 start() 메소드외에 다른 메소드를 호출하지 않을 경우 참조변수에
// Thread 객체를 저장하지 않고 Thread 객체 생성시 start() 메소드를 직접 호출
// 객체 생성하자마자 start() 호출
new MultiThreadOne().start();
new MultiThreadOne().start();
/*
// 참조변수 만들어서 사용하면 비효율
MultiThreadTwo two = new MultiThreadTwo();
// Thread(Runnable target)
Thread thread = new Thread(two);
thread.start();
*/
// 효율적인 처리방법
new Thread(new MultiThreadTwo()).start();
// Runnable 인터페이스를 상속받은 자식클래스로 객체를 여러개 생성할 필요가 없는 경우
// Runnable 인터페이스를 상속받은 익명클래스로 객체를 생성해 Thread 클래스의
// 생성자 매개변수에 전달하여 Thread 객체 생성
/*
// 익명 클래스로 객체 생성(지역 클래스)
new Thread(new Runnable() {
// 인터페이스가 가지고 있는 메소드 다 오버라이딩 해야됨
@Override
public void run() {
for(char i = 'a'; i <= 'z'; i++){
System.out.print(i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start();
*/
// Runnable 인터페이스에는 반환형이 [void]이고 매개변수가 없는 run() 메소드가 작성된
// 함수형 인터페이스로 사용 가능
// => 람다표현식을 사용하여 객체 생성 가능
new Thread(() -> {
for(char i = 'a'; i <= 'z'; i++){
System.out.print(i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
for(int i = 1; i <= 9; i++){
System.out.print(i);
Thread.sleep(500);
}
}
}