위로
아래
스레드
- 우선순위 개념이 없다
- start() 하면 준비 상태가 된다
- run() 하면 실행 상태가 된다
- 스레드는 같은 이름으로 메소드를 실행하는 게 아니라, start() 메소드를 호출하면 run() 메소드를 실행한다.
Thread 클래스와 Runnable 인터페이스
Thread 클래스
- Thread 클래스는 java.lang 패키지에 포함되어 있다. (import가 필요 없다)
Runnable 인터페이스
- Runnable 인터페이스는 java.lang 패키지에 포함되어 있다. (import가 필요 없다)
- 구현 클래스를 통해서 스레드를 생성한다.
- 유일한 멤버로 run() 메소드를 가지고 있다 (구현 클래스에서 run() 메소드를 구현해야 한다)
스레드 생성 2가지 방법
두 가지 방법
- Thread 클래스를 상속 받아 run() 메소드를 오버라이딩
- Runnable 인터페이스를 구현(impleaments)하여 run() 메소드를 정의
스레드 생성 방법이 두 가지인 이유
- 자바는 단일 상속이기 때문.
- 다른 클래스를 상속받아야 하면 Thread 클래스까지 상속 받아 스레드를 생성할 수 없다.
- 그래서 Runnable 인터페이스로 스레드가 수행할 작업 코드를 작성한 후 스레드를 생성한다.
스레드 생성 2가지 방법 : Thread 자식 클래스 정의
// Thread 자식 클래스 정의
class Mythread extends Thread {
//스레드가 실행할 코드
}
// Thread 자식 객체 생성
Thread thread = new Mythread();
// 스레드 실행
thread.start();
생성자
- Thread() : 스레드 객체 생성
- Thread(Runnable target) : Runnable 구현 객체를 사용해 스레드 객체를 생성
- Thread(Runnable target, String name) : Runnable 구현 객체를 사용해 스레드 이름이 name인 스레드 객체를 생성.
메소드
- static Thread currentThread() : 현재 실행 중인 스레드 객체의 참조 값을 반환
- getName() : 스레드의 이름을 반환 (String)
- getPriority() : 스레드의 우선순위 값을 반환 (int)
- isInterrupted() : 스레드가 인터럽트를 당했는지 여부를 반환 (boolean)
- setName() : 스레드의 이름을 설정 (void)
- setPriority() : 스레드의 우선순위를 설정 (void)
예시 (상속을 못 받는 경우)
더보기
// Thread로부터 단일 상속만 받는 클래스 WorkerThread.java 파일
public class WorkerThread extends Thread {
public void run() {
for (int i=0; i<5; i++) {
System.out.print("잘가. ");
try {
Thread.sleep(500);
} catch (InterruptedException e) {}
}
}
}
// 스레드 하나를 가지고 있는 메인 클래스 Thread4Demo.java
public class Thread4Demo {
public static void main(String[] args) {
Thread t = new WorkerThread();
t.start();
for(int i=0;i<5;i++) {
System.out.print("안녕. ");
try {
Thread.sleep(500);
} catch (InterruptedException e) {}
}
}
}
스레드 생성 2가지 방법 : Runnable 구현 클래스 정의
// Runnable 구현 클래스 정의
class RunnableClass implements Runnable {
public void run(){
// 스레드가 실행할 코드
}
}
// Thread 객체 생성
Thread thread = new Thread(new RunnableClass());
// 스레드 실행
thread.start();
- run() 메소드에 작업 스레드가 실행할 코드를 추가하면 된다.
- Runnable 구현 클래스는 스레드 자체가 아니라, 스레드가 실행할 코드만 포함하는 클래스이다.
- Runnable 구현 클래스로 생성한 객체를 Thread() 생성자의 인수로 사용해야 비로소 작업 스레드의 객체가 생성된다.
예시
더보기
// 메인 클래스 Thread1Demo.java 파일 (메인 클래스도 하나의 스레드다)
public class Thread1Demo {
public static void main(String[] args) {
Thread t = new Thread (new MyRunnable());
t.start();
for(int i=0 ; i<5 ; i++) {
System.out.print("안녕.");
try {
Thread.sleep(500);
} catch(InterruptedException e) {}
}
}
}
// Runnable 구현 클래스 MyRunnable.java 파일 (따로 구현한 스레드)
class MyRunnable implements Runnable {
public void run() {
for(int i=0;i<5;i++) {
System.out.print("잘가.");
try {
Thread.sleep(500);
} catch(InterruptedException e) {}
}
}
}
원래 위에부터 차례로 진행되겠지만, 스레드로 둘이 동시 진행을 해서, 둘이 같이 찍힌다.
메인 클래스도 하나의 스레드다.
Runnable 구현 클래스 축약 과정
익명 구현 객체 사용
// 익명 구현 객체 사용
Thread thread = new Thread(new Runnable(){
public void run(){
// 스레드가 실행할 코드
}
});
thread.start();
thread 변수 제거
new Thread(new Runnable() {
public void run(){
// 스레드가 실행할 코드
}
}).start();
람다식 사용
new Thread(() -> {
// 스레드가 실행할 코드
}).start();
예시
더보기
public class Thread5Demo {
public static void main(String[] args) {
new Thread() {
public void run() {
for (int i=0 ; i<5 ; i++) {
System.out.print("잘가. ");
try {
Thread.sleep(500);
} catch (InterruptedException e) {}
}
}
}.start();
for(int i=0;i<5;i++) {
System.out.print("안녕. ");
try {
Thread.sleep(500);
} catch (InterruptedException e) {}
}
}
}
스레드 풀
스레드 풀 (thread pool)
- 제한된 개수의 스레드를 JVM이 관리하도록 맡기는 방식
- 사용 이유 : 스레드 개수가 많아지면 CPU와 메모리에 많은 부하가 발생하므로 동시에 실행하는 스레드 개수를 제한할 필요가 있다.
- 스레드풀을 이용하면 개발자가 스레드를 생성할 필요가 없다.
- 실행할 작업을 스레드풀로 전달하면 JVM이 스레드 풀의 유휴 스레드(idle thread) 중 하나를 선택해서 스레드로 실행시킨다
예시
더보기
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class ThreadPoolDemo {
public static void main(String[] args) {
Runnable task = () -> {
for (int i=0 ; i<5 ; i++) {
System.out.print("잘가. ");
try {
Thread.sleep(500);
} catch (InterruptedException e) {}
}
};
ExecutorService exec = Executors.newCachedThreadPool();
exec.execute(task);
for(int i=0; i<5; i++) {
System.out.print("안녕. ");
try {
Thread.sleep(500);
} catch (InterruptedException e) {}
}
exec.shutdown();
}
}