위로 아래

스레드

  1. 우선순위 개념이 없다
  2. start() 하면 준비 상태가 된다
  3. run() 하면 실행 상태가 된다
  4. 스레드는 같은 이름으로 메소드를 실행하는 게 아니라, start() 메소드를 호출하면 run() 메소드를 실행한다.

 

 


Thread 클래스와 Runnable 인터페이스

Thread 클래스

  1. Thread 클래스는 java.lang 패키지에 포함되어 있다. (import가 필요 없다)

 

Runnable 인터페이스

  1. Runnable 인터페이스는 java.lang 패키지에 포함되어 있다. (import가 필요 없다)
  2. 구현 클래스를 통해서 스레드를 생성한다.
  3. 유일한 멤버로 run() 메소드를 가지고 있다 (구현 클래스에서 run() 메소드를 구현해야 한다)

 

 

 


스레드 생성 2가지 방법

두 가지 방법

  1. Thread 클래스를 상속 받아 run() 메소드를 오버라이딩
  2. Runnable 인터페이스를 구현(impleaments)하여 run() 메소드를 정의

 

스레드 생성 방법이 두 가지인 이유

  1. 자바는 단일 상속이기 때문.
  2. 다른 클래스를 상속받아야 하면 Thread 클래스까지 상속 받아 스레드를 생성할 수 없다.
  3. 그래서 Runnable 인터페이스로 스레드가 수행할 작업 코드를 작성한 후 스레드를 생성한다.

 

 

스레드 생성 2가지 방법 : Thread 자식 클래스 정의

// Thread 자식 클래스 정의
class Mythread extends Thread {
	//스레드가 실행할 코드
}


// Thread 자식 객체 생성
Thread thread = new Mythread();


// 스레드 실행
thread.start();

 

생성자

  1. Thread() : 스레드 객체 생성
  2. Thread(Runnable target) : Runnable 구현 객체를 사용해 스레드 객체를 생성
  3. Thread(Runnable target, String name) : Runnable 구현 객체를 사용해 스레드 이름이 name인 스레드 객체를 생성.

메소드

  1. static Thread currentThread() : 현재 실행 중인 스레드 객체의 참조 값을 반환
  2. getName() : 스레드의 이름을 반환 (String)
  3. getPriority() : 스레드의 우선순위 값을 반환 (int)
  4. isInterrupted() : 스레드가 인터럽트를 당했는지 여부를 반환 (boolean)
  5. setName() : 스레드의 이름을 설정 (void)
  6. 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();
  1. run() 메소드에 작업 스레드가 실행할 코드를 추가하면 된다.
  2. Runnable 구현 클래스는 스레드 자체가 아니라, 스레드가 실행할 코드만 포함하는 클래스이다.
  3. 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)

  1. 제한된 개수의 스레드를 JVM이 관리하도록 맡기는 방식
  2. 사용 이유 : 스레드 개수가 많아지면 CPU와 메모리에 많은 부하가 발생하므로 동시에 실행하는 스레드 개수를 제한할 필요가 있다.
  3. 스레드풀을 이용하면 개발자가 스레드를 생성할 필요가 없다.
  4. 실행할 작업을 스레드풀로 전달하면 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();
	}
}