- 동일 프로세스 내에 '독립'적인 다중 수행하는 프로그램 단위
- 병행성 증진. 처리율 향상, 응답속도 향상 목적
- 자바에서 쓰레드를 만들어서 사용하는 방법1:
- Thread 클래스를 상속받는 클래스를 정의
- 정의한 클래스에서 run() 메소드를 override - 쓰레드에서 할 일을 구현
- Thread 클래스의 인스턴스를 생성
- 생성된 인스턴스에서 start() 메소드를 호출
package com.lec.java.thread01;
public class Thread01Main {
public static void main(String[] args) {
System.out.println("쓰레드 생성 1");
// 3. Thread 클래스의 인스턴스를 생성
Thread th1 = new MyThread("Hello, Java!"); // 다형성
Thread th2 = new MyThread("안녕하세요~");
// 4. 생성된 인스턴스에서 start() 메소드를 호출
th1.start();
th2.start();
// Thread 클래스의 start() 메소드를 호출하면,
// 내부적으로 run() 메소드가 호출됨
// start() 메소드가 호출되어야 OS에 의해서 쓰레드로 동작을 하게 됨
// run() 메소드를 직접 호출하는 경우는 쓰레드로 동작하는 것이 아니라,
// 단순히 run() 메소드만 실행이 되는 것임.
// 이때 발생하는 호출스택 관계도는 '자바의 정석' p626 그림 참조. p628,629 예제
System.out.println("=======================");
System.out.println("여기는 언제 출력될까요?");
System.out.println("=======================");
// 하나의 쓰레드는 start() 가 딱 한번만 호출될수 있다.
// 만약 아래와 같이 다시 start() 하면 IllegalThreadStateException 발생
// th1.start();
// 아래와 같이 새로 생성해서 사용하면 가능
th1 = new MyThread("Hello Java2");
th1.start();
} // end main()
} // end class
// 1. Thread 클래스를 상속받는 클래스를 정의
class MyThread extends Thread{
private String msg;
private int count;
public MyThread() {}
public MyThread(String msg) {
this.msg = msg;
count = 0;
}
// 2. 정의한 클래스에서 run() 메소드를 override
// 쓰레드에서 할 일을 구현
@Override
public void run() {
for(int i = 0; i < 100; i++) {
System.out.println(getName() + " " + count + " : " + msg);
count++;
}
}
} // end class MyThread
Runnable 인터페이스로 쓰레드 구현
자바는 다중 상속을 지원하지 않음
-> 다른 클래스를 상속받고 있는 경우에는,
Thread 클래스를 상속받을 수 없는 문제가 발생
-> 인터페이스를 구현해서 쓰레드를 생성할 수 있는 방법을 제공
쓰레드 사용 방법 2:
1. Runnable 인터페이스를 구현하는 클래스를 정의
2. 정의한 클래스에서 run() 메소드를 override
3. Runnable을 구현하는 클래스의 인스턴스를 생성
4. 만들어진 인스턴스를 Thread 생성자의 매개변수로 주면서, Thread 인스턴스를 생성
5. 생성된 Thread 인스턴스의 start() 메소드를 호출
package com.lec.java.thread02;
public class Thread02Main {
public static void main(String[] args) {
System.out.println("쓰레드 생성 2");
// 3. Runnable을 구현하는 클래스의 인스턴스를 생성
Runnable runnable1 = new MyRunnable("안녕~ 자바!");
Runnable runnable2 = new MyRunnable("Hello Java!");
Runnable runnable3 = new MyRunnable("멀티 쓰레드");
// 4. Runnable을 이용해서 Thread 인스턴스를 생성
Thread th1 = new Thread(runnable1);
Thread th2 = new Thread(runnable2);
// 5. Thread 인스턴스의 start() 메소드를 호출
th1.start();
th2.start();
new Thread(runnable3).start();
new Thread(new MyRunnable("Java Thread")).start();
// Anonymous class 로 생성
System.out.println();
System.out.println("Anonymous class 으로 Runnable 구현");
new Thread(new Runnable() {
@Override
public void run() {
for(int i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + " 익명클래스 " + i);
}
}
}).start();
// Runnable 인터페이스는 run() 가상메소드 하나만 가지고 있는 인터페이스 이기 때문에
// Lambda-expression 으로도 구현 가능.
System.out.println();
System.out.println("Lambda-expression 으로 Runnable 구현");
new Thread(()->{
for(int i = 1; i < 100; i ++) {
System.out.println(Thread.currentThread().getName() + " Lambda " + i);
}
}).start();
System.out.println("-- main() 종료 -- ");
} // end main()
} // end class
// 1. Runnable 인터페이스를 구현하는 클래스를 정의
class MyRunnable implements Runnable{
private String msg;
private int count;
public MyRunnable() {}
public MyRunnable(String msg) {
this.msg = msg;
this.count = 0;
}
// 2. 정의한 클래스에서 run() 메소드를 override - 쓰레드 할 일
@Override
public void run() {
for(int i = 0 ; i < 100 ; i++) {
System.out.println(Thread.currentThread().getName() + " " + count + " : " + msg);
count++;
}
}
} // end class MyRunnable