JAVA

[JAVA] 쓰레드

shb 2022. 2. 18. 18:31

쓰레드 Thread
 *  동일 프로세스 내에 '독립'적인 다중 수행하는 프로그램 단위
 *  병행성 증진처리율 향상응답속도 향상 목적

 *  자바에서 쓰레드를 만들어서 사용하는 방법1:
  1. Thread 클래스를 상속받는 클래스를 정의
  2. 정의한 클래스에서 run() 메소드를 override - 쓰레드에서 할 일을 구현
  3. Thread 클래스의 인스턴스를 생성
  4. 생성된 인스턴스에서 start() 메소드를 호출

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() 메소드를 호출

 

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

쓰레드 우선 순위(priority)
 setPriority(): Thread 클래스가 가지고 있는 메소드
 쓰레드의 우선순위(priority)를 변경하는 기능
 Thread 클래스에 정의된 우선순위:
 MAX_PRIORITY(10), MIN_PRIORITY(1), NORM_PRIORITY(5)
 대부분의 시스템(OS)에서는 우선순위가 높은 쓰레드에게만 실행 기회를 부여

 main() 메소드의 priotiry는 5 이다
 priotiry 는 상대적이다  2 : 1 <=> 10 : 9 

 

 

join() 
 지정한 시간동안은 쓰레드가 실행되도록 둔다.
 지정한 시간이 지나거나, 작업이 종료되면 (쓰레드가 종료되면)  join()을 호출한 쓰레드로 돌아와 실행을 한다
 특정 쓰레드가 종료한 시점을 기다릴 필요가 있을때  사용

 

sleep() 
 지정된 시간 동안 쓰레드 일시 정지

 

 

'JAVA' 카테고리의 다른 글

[JAVA] 파일 입출력  (0) 2022.02.22
[JAVA] 람다 표현식  (0) 2022.02.18
[JAVA] 내부 클래스  (0) 2022.02.17
[JAVA] Collection  (0) 2022.02.17
[JAVA] Wrapper 클래스  (0) 2022.02.17