개발자가 직접 스레드를 생성하여 여러 명령이 동시에 실행되도록 프로그램 작성하는 것이다.
개발자가 스레드를 생성하여 명령 실행 👉 프로그램의 모든 스레드가 소멸되면 프로그램이 종료
JVM에 의해 main 스레드는 자동 생성 되며,
main 스레드 외 다른 스레드를 생성하여 명령 실행한다.
Thread 클래스를 상속받은 자식 클래스를 만들고 run() 메소드 오버라이드 선언한다.
//자식 클래스
public class MultiThreadOne extends Thread {
@Override
public void run() {
//새로운 스레드로 실행될 명령 작성
for(char i='A';i<='Z';i++) {
System.out.print(i);
}
}
}
Thread 인스턴스로 start() 메소드를 호출하여 스레드 생성한다.
생성된 스레드는 자동으로 run() 메소드의 명령 실행한다.
Thread 클래스를 상속받은 자식 클래스로 인스턴스 생성한다.
자식 클래스의 생성자로 인스턴스를 생성하여 부모(Thread) 인스턴스가 먼저 생성된다.
부모(Thread) 인스턴스의 start() 메소드를 호출하여 스레드 생성한다.
생성된 스레드는 자식 클래스에서 오버라이드 선언된 run() 명령 실행된다.
public class MultiThreadApp {
//main 메소드에서 전달되는 모든 예외는 JVM이 자동으로 예외 처리
//JVM에 의해 main 스레드 자동 생성
public static void main(String[] args) throws InterruptedException {
new MultiThreadOne().start();
for(char i='0'; i<='9'; i++) {
System.out.print(i);
Thread.sleep(500);
}
}
}
Thread 클래스를 상속 받지 못할 경우(이미 다른 클래스를 상속 받고 있을 때) 사용한다.
Runnable 인터페이스를 상속받는 자식 클래스 만들고, 자식 클래스에서 run 메소드를 오버라이드 선언한다.
//자식 클래스
public class MultiThreadTwo implements Runnable{
@Override
public void run() {
for(char i='a';i<='z';i++) {
System.out.print(i);
}
}
}
Runnable 인터페이스를 상속받은 클래스로 인스턴스 생성한다.
Runnable 인스턴스를 전달받아 Thread 인스턴스 생성하는 생성자 호출하며, 이는 run() 메소드가 오버라이드 선언되는 것과 같은 효과가 생긴다.
Thread 인스턴스로 start() 메소드를 호출한다.
새로운 스레드를 생성하여 run() 명령 실행한다.
//참조 변수를 만드는 경우
Thread thread = new Thread(multiThreadTwo);
thread.start();
//한번만 호출 가능해서 변수를 선언하지 않아도 된다.
//참조 변수를 만들지 않는 경우 -> 가독성 증가
new Thread(new MultiThreadTwo()).start();
우선순위 기본 값: 5
Thread에 우선순위를 새롭게 지정할 수 있다.
PriorityOne one = new PriorityOne();
PriorityTwo two = new PriorityTwo();
one.setPriority(Thread.MIN_PRIORITY);//상수값: 1, 우선순위가 낮음
two.setPriority(Thread.MAX_PRIORITY);//상수값: 10, 우선순위가 높음
동일한 run() 메소드의 명령을 실행하는 다수의 스레드에서 인스턴스 필드값 변경 관련 동일 메소드 호출시 조작에 대한 잘못된 결과를 반환 받을 수 있다.
@Override
public void run() {
//다수의 스레드에서 인스턴스 필드값 변경 관련 동일 메소드 호출
명령...
}
스레드의 메소드 호출에 대한 스레드 일시 중지 기능이다.
다수의 스레드가 인스턴스 필드값 변경 관련 동일 메소드를 호출할 경우
먼저 호출 요청한 스레드에 대한 처리 결과가 제공될 때까지 다른 스레드의 메소드 호출에 대한 명령 처리를 일시 중지(Method Lock)한다.
public synchronized void deposit(String name, int amount){//입금 처리 메소드
balance+=amount;
System.out.println("[입금]"+name+"님이 "+amount+"원 입금하여 잔액은 "+balance+"원입니다.");
}
2.동기화 영역(synchronized Block): 인스턴스를 전달받아 인스턴스의 모든 메소드를 동기화 처리하여 호출한다.
@Override
public void run() {
//account가 들어간 모든 메소드가 동기화 처리
synchronized (account) {
account.withDraw(userName, 2000);
}
}