티스토리 뷰

배운 것 기록/java

Thread

키죽 2022. 6. 28. 19:23

 프로세스 (Process)
 - 프로그램을 실행하여 메모리에 로딩된 상태 (= 실행 중인 프로그램)
 - 멀티태스킹 (Multi Tasking)
=> 프로세스가 여러 개 일때 해당 프로세스들이 동시에 수행되는 것처럼 보이는 것으로 정확히는 CPU가 빠른 속도로 프로세스들을 번갈아가며 처리한다.


쓰레드 (Thread)

- 프로세스 내에서 작업의 최소 단위로 하나의 프로세스 내에 쓰레드 한 개 (= Single Thread)일 때, 해당 프로세스 내에서 동시에 수행 가능한 작업은 단 하나 뿐이다.
- 하나의 프로세스 내에서 동시에 수행 가능한 작업을 늘리려면 멀티 쓰레딩을 구현 해야한다!
 ex) 메신저에서 파일 전송과 함께 메세지 송신, 수신을 동시에 수행하는 것

 

기본 프로그램의 경우(쓰레드 적용x)

package thread;

public class Ex1 {

	public static void main(String[] args) {
    
    	NoThread nt1 = new NoThread("AAA", 1000);
		NoThread nt2 = new NoThread("BBB", 1000);
		NoThread nt3 = new NoThread("CCC", 1000);
		
		nt1.run();	// A작업이 1000번 수행이 끝나면
		nt2.run();	// B작업이 실행, B작업이 1000번 수행이 끝나면
		nt3.run();	// C작업 실행됨
		// 기본적인 프로그램은 앞의 코드가 실행이 끝나야만 다음 코드가 실행된다!
		
	}
}

class NoThread {
	String str;
	int count;
	
	public NoThread(String str, int count) {
		this.str = str;
		this.count = count;
	}
	
	public void run() {
		// count 횟수만큼 str 반복 출력
		for(int i = 1; i <= count; i++) {
			System.out.println(i + " : " + str);
		}
	}
}

멀티 쓰레딩 (Multi Threading)

- 하나의 프로세스 내에서 두 가지 이상의 작업을 동시에 처리하는 것으로 실제로는 두 가지 이상의 작업을 동시에 수행하는 것이 아니며 CPU가 빠른 속도로 여러 작업을 번갈아가며 수행하기 때문에 동시에 수행되는 것 처럼 느껴진다. (Round Robin 방식)
- 멀티쓰레딩으로 처리되는 작업 순서는 계속 바뀌므로 실행결과가 달라질 수 있다.
  


< 멀티 쓰레딩 구현 방법 >

1. Thread 클래스를 상속받는 서브클래스를 정의하는 방법

1) 멀티쓰레딩 코드가 포함될 서브클래스에서 Thread 클래스를 상속한다.
2) Thread 클래스의 run() 메서드를 오버라이딩하여 멀티쓰레딩으로 처리할 코드를 기술한다.
3) 멀티쓰레딩 클래스 인스턴스 생성 후,
4) start() 메서드를 호출하여 멀티쓰레딩 시작한다.

 

멀티쓰레딩 구현 시 무작위로 출력된다. (단, 횟수가 너무 적으면 무작위로 나오지 않을 수도 있음)

package thread;

public class Px2 {

	public static void main(String[] args) {

		MyThread mt1 = new MyThread("AAA", 1000);
		MyThread mt2 = new MyThread("BBB", 1000);
		MyThread mt3 = new MyThread("CCC", 1000);
		
//	 	run() 메서드를 호출하면 멀티쓰레딩이 아닌 싱글쓰레딩으로 처리된다!
//		mt1.run();
		
		mt1.start();
		mt2.start();
		mt3.start();
		
	}

}

class MyThread extends Thread {
	String str;
	int count;
	
	public MyThread(String str, int count) {
		this.str = str;
		this.count = count;
	}

	@Override
	public void run() {
		for(int i=1; i <= count; i++) {
			System.out.println(i + " : " + str);
		}
	}
}

 

 

2. Runnable 인터페이스를 구현하는 서브클래스를 정의하는 방법

 - 기존에 다른 클래스를 상속 중인 서브클래스는 Thread 클래스 상속이 불가능하므로 Thread 클래스 상속 대신 Runnable 인터페이스를 구현한다. (Thread 클래스는 Runnable 인터페이스의 구현체)
- Runnable 인터페이스 내에는 start() 메서드가 존재하지 않으며, 존재 하더라도 추상메서드 형태이기 때문에 start() 메서드 호출이 불가능하다. 따라서, Thread 클래스를 통해 간접적으로 start() 메서드를 호출해야한다!

 

1) 멀티쓰레딩 코드가 포함될 서브클래스에서 Runnable 인터페이스를 구현한다.
2) 추상메서드인 run() 메서드를 구현하고 오버라이딩하여 멀티쓰레딩 코드 기술한다.

3) 멀티쓰레딩 클래스 인스턴스 생성한다.
! 주의 ! Runnable 인터페이스 내에 start() 메서드가 존재하지 않음
4) start() 메서드를 가진 Thread 클래스의 인스턴스 생성 => 생성자 파라미터로 Runnable 구현체 객체 전달
5) Thread 인스턴스를 통해 간접적으로 start() 메서드 호출한다.

 

package thread;

public class Px3 {

	public static void main(String[] args) {

		YThread yt1 = new YourThread("AAA", 100000);
		YThread yt2 = new YourThread("BBB", 100000);
		Runnable yt3 = new YourThread("CCC", 100000); // YThread -> Runnable 업캐스팅
		
// 		Runnable 구현체 내부에는 start() 메서드가 존재하지 않는다!
//		yt3.start();
		
		// Thread 클래스의 인스턴스 생성 시 생성자 파라미터로 Runnable 구현체 객체 전달 후
		// Thread 객체를 통해 start() 메서드를 호출하여 간접적으로 멀티쓰레딩 수행
		Thread t1 = new Thread(yt1);
		Thread t2 = new Thread(yt2);
		Thread t3 = new Thread(yt3);
        	t1.start();
		t2.start();
		t3.start();
		
	}

}

class A {}
class YThread extends A implements Runnable {

	String str;
	int count;
	
	public YThread(String str, int count) {
		this.str = str;
		this.count = count;
	}

	@Override
	public void run() {
		for(int i=1; i <= count; i++) {
			System.out.println(i + " : " + str);
		}
	}
}

 

YThread 타입 변수는 Thread 클래스 생성자에 전달하는 작업 외에 사용되지 않으므로, 1회성 변수를 선언하기 보다는 Thread 생성자에 YThread 객체 생성 코드를 직접 전달하여 변수 없이 객체 자체를 바로 전달이 가능하다.

Thread t1 = new Thread(new YThread("AAA", 1000));
Thread t2 = new Thread(new YThread("BBB", 1000));
Thread t3 = new Thread(new YThread("CCC", 1000));
		
t1.start();
t2.start();
t3.start();

 

Thread 상태 제어

- Thread.sleep() 메서드를 호출하여 일시 정지가 가능하다.

- 특정 쓰레드에 대한 타이머 기능을 부여하기 위한 용도로 사용하거나 쓰레드 간의 우선순위로 인한 기아(Starvation) 상태를 방지하는 용도로 사용된다.

 

new Thread(new Runnable() {
			
	@Override
	public void run() {
				
		for(int i=1; i <= 60; i++) {
					
			try {
				Thread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}	
				System.out.println(LocalTime.now());
			}		
		}
	}).start();

실행하면 아래와 같이 출력된다.

 

 

'배운 것 기록 > java' 카테고리의 다른 글

Formatting - SimpleDataFormat, DateTimeFormatter  (0) 2022.07.11
람다식 표현과 this  (0) 2022.07.02
StringBuilder / StringBuffer  (0) 2022.06.25
Generic  (0) 2022.06.22
String 메서드  (0) 2022.06.21
댓글
최근에 올라온 글
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31
글 보관함