πŸ“• Language/Java

[Java] Thread κ΅¬ν˜„ 예제

a n u e 2022. 3. 5. 17:40

Thread : ν”„λ‘œμ„ΈμŠ€ μ•ˆμ—μ„œμ˜ ν•˜λ‚˜μ˜ 흐름

μžλ°”λŠ” Multi Thread 지원 (λŒ€κΈ° 쀑, λ‹€λ₯Έ 일을 μ²˜λ¦¬ν•˜μ—¬ 처리 속도 ν–₯상)

 

Thread κ΅¬ν˜„ν•˜λŠ” 법은 두 κ°€μ§€κ°€ μžˆλ‹€.

첫째, Thread classλ₯Ό μƒμ†λ°›μ•„μ„œ μ‚¬μš©

λ‘˜μ§Έ, Runnable classλ₯Ό μƒμ†λ°›μ•„μ„œ μ‚¬μš©

μžλ°”λŠ” 닀쀑 상속을 ν—ˆμš©ν•˜μ§€ μ•ŠμœΌλ―€λ‘œ, 타 클래슀λ₯Ό μƒμ†λ°›μ•„μ•Όν•˜λŠ” κ²½μš°λ•Œλ¬Έμ— 2λ²ˆμ„ 주둜 μ‚¬μš©

 

Runnable을 μ‚¬μš©ν•˜μ—¬ Threadλ₯Ό κ΅¬ν˜„ν•΄λ³΄μž!

 

κΈ°λ³Έ κ΅¬ν˜„

package study;

//Runnable interface μƒμ†λ°›λŠ” λ°©μ‹μœΌλ‘œ Thread κ΅¬ν˜„ (run() method κ΅¬ν˜„ ν•„μˆ˜)
public class ThreadSample implements Runnable {
	
	private String TEMPLATE = "좜λ ₯쀑 [%s][%d회]";
	private String threadName;
	//μƒμ„±μž
	public ThreadSample (String threadName) {
		this.threadName = threadName;
	}
	
	@Override
	public void run() {
		for(int i=0; i<=100; i++) {
			System.out.println(String.format(TEMPLATE, threadName, i));
		}
	}

	public static void main(String[] args) {
		ThreadSample run1 = new ThreadSample("thread1");
		ThreadSample run2 = new ThreadSample("thread2");
		ThreadSample run3 = new ThreadSample("thread3");
		
		Thread thread1 = new Thread(run1);
		Thread thread2 = new Thread(run2);
		Thread thread3 = new Thread(run3);
		
		thread1.start();
		thread2.start();
		thread3.start();
	}
}

 

Thread Pool 예제

Threadλ₯Ό μ œν•œλœ 개수만큼 λ§Œλ“€μ–΄λ†“κ³ , μž‘μ—… 큐에 λ“€μ–΄μ˜€λŠ” μž‘μ—…λ“€μ„ Threadκ°€ ν•˜λ‚˜μ”© λ§‘μ•„μ„œ μ²˜λ¦¬ν•˜λŠ” 방식

package study;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

//Runnable interface μƒμ†λ°›λŠ” λ°©μ‹μœΌλ‘œ Thread κ΅¬ν˜„ (run() method κ΅¬ν˜„ ν•„μˆ˜)
//Thread pool μ΄μš©ν•˜μ—¬ 생성 μ‹œ, μ΅œλŒ€ 개수λ₯Ό μ œν•œ μ§€μ •
public class ThreadPoolSample implements Runnable {
	
	private String TEMPLATE = "좜λ ₯쀑 [%s][%d회]";
	private String threadName;
	//μƒμ„±μž
	public ThreadPoolSample (String threadName) {
		this.threadName = threadName;
	}
	
	@Override
	public void run() {
		for(int i=0; i<=100; i++) {
			System.out.println(String.format(TEMPLATE, threadName, i));
		}
	}

	public static void main(String[] args) {
		ThreadPoolSample run1 = new ThreadPoolSample("thread1");
		ThreadPoolSample run2 = new ThreadPoolSample("thread2");
		ThreadPoolSample run3 = new ThreadPoolSample("thread3");
		
		//직접 Thread μƒμ„±ν•˜μ§€ μ•Šκ³ , Thread pool μƒμ„±ν•˜μ—¬ 개수λ₯Ό 3개둜 μ œν•œν•˜κ³  싀행함
		ExecutorService executorService = Executors.newFixedThreadPool(3);
		executorService.execute(run1);
		executorService.execute(run2);
		executorService.execute(run3);
		
		executorService.shutdown();
		
		try {
			/**
			 * awaitTermination() 
			 * ν•΄λ‹Ή μ‹œκ°„ 만큼 μ œν•œμ„ 두고, κ·Έ μ‹œκ°„ μ•ˆμ— Thread pool μž‘μ—…μ΄ μ „λΆ€ μˆ˜ν–‰λ˜μ§€ λͺ»ν•˜λ©΄ 
			 * μ‹€ν–‰ μ€‘μ΄λ˜ Thread에 μΈν„°λŸ½νŠΈ λ°œμƒ(.interrupt())ν•˜κ³  false λ°˜ν™˜
			 * μΈν„°λŸ½νŠΈλž€? μŠ€λ ˆλ“œκ°€ μΌμ‹œμ •μ§€ μƒνƒœμ— μžˆμ„λ•Œ, InterruptedException μ˜ˆμ™Έ λ°œμƒμ„ ν•˜λŠ” μ—­ν• 
			 * 이것을 μ΄μš©ν•˜λ©΄ μŠ€λ ˆλ“œμ˜ run() λ©”μ†Œλ“œλ₯Ό 정상 μ’…λ£Œ μ‹œν‚¬ 수 있음
			 */
			if(!executorService.awaitTermination(5, TimeUnit.MINUTES)) {
				//shutdown() : μ‹€ν–‰ 쀑인 μž‘μ—… 뿐 μ•„λ‹ˆλΌ, μž‘μ—… 큐에 λŒ€κΈ° 쀑인 λͺ¨λ“  μž‘μ—…μ„ λ‹€ μ²˜λ¦¬ν•˜κ³  Thread pool 쀑지
				//shutdownNow() : μΈν„°λŸ½νŠΈλ‘œ μ¦‰μ‹œ 쀑지함!
				executorService.shutdownNow();
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
			executorService.shutdownNow();
		}
	}
}

 

 

잠깐! μ—¬κΈ°μ„œ Thread pool은 3개둜 μ œν•œν•˜κ³ , Runnable κ°μ²΄λŠ” 4개λ₯Ό λ§Œλ“ λ‹€λ©΄ μ½˜μ†”μ— μ–΄λ–»κ²Œ 찍힐까?

μ•žμ„  객체인 Thread1~3이 100κΉŒμ§€ μ‹€ν–‰λ˜κ³ , 싀행이 λλ‚˜λ©΄ λ‹€μŒ 객체인 Thread4κ°€ 돌며 100κΉŒμ§€ μ°λŠ”λ‹€.

 

 

 

Interrupt κ΅¬ν˜„

μŠ€λ ˆλ“œλŠ” μžμ‹ μ˜ run() λ©”μ†Œλ“œκ°€ λͺ¨λ‘ μ‹€ν–‰λ˜λ©΄, μžλ™μœΌλ‘œ μ’…λ£Œλœλ‹€. κ·ΈλŸ¬λ‚˜ μŠ€λ ˆλ“œλ₯Ό μ¦‰μ‹œ μ’…λ£Œν•΄μ•Ό ν•  μˆ˜λ„ μžˆλŠ”λ°, 이런 κ²½μš°μ— interruptκ°€ μ“°μ—¬μ§„λ‹€. (stop은 deprecated λ˜μ—ˆλ‹€.)
μ£Όμ˜μ μ€! μŠ€λ ˆλ“œκ°€ μ‹€ν–‰ λŒ€κΈ°λ‚˜, μ‹€ν–‰ μƒνƒœμ—μ„œ interrupt() methodκ°€ μ‹€ν–‰λ˜λ©΄ μ˜ˆμ™Έκ°€ λ°œμƒν•˜μ§€ μ•ŠλŠ”λ‹€. λ°˜λ“œμ‹œ, μΌμ‹œμ •μ§€ μƒνƒœκ°€ μžˆμ–΄μ•Ό InterruptedException μ˜ˆμ™Έκ°€ λ°œμƒν•œλ‹€. κ·Έλž˜μ„œ sleep methodλ₯Ό μ΄μš©ν•˜μ—¬ 예제λ₯Ό κ΅¬ν˜„ν•΄λ³΄μ•˜λ‹€.

 

package study.thread;

public class InterruptSample {
	//1초 ν›„, μŠ€λ ˆλ“œ μ€‘μ§€μ‹œν‚΄
	public static void main(String[] args) {
		Thread thread = new ThreadPrint();
		thread.start();
		
		try {
			//μΌμ‹œμ •μ§€μ—¬μ•Όλ§Œ μ˜ˆμ™Έκ°€ λ°œμƒν•˜λ―€λ‘œ
			Thread.sleep(1000); 
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		//μΌμ‹œμ •μ§€κ°€ λ˜μ–΄ 에외가 λ°œμƒν–ˆκ³ , μŠ€λ ˆλ“œλ₯Ό μ’…λ£Œμ‹œν‚€κΈ° μœ„ν•΄ interrupt call
		//Thread μ’…λ£Œ μœ„ν•΄ InterruptedException λ°œμƒμ‹œν‚΄
		thread.interrupt();
	}
}
package study.thread;

//μ΄λ²ˆμ—” Thread classλ₯Ό μƒμ†λ°›λŠ” λ°©λ²•μœΌλ‘œ κ΅¬ν˜„
public class ThreadPrint extends Thread {
	
	@Override 
	public void run() {
		try {
			while(true) { 
				System.out.println("싀행쀑");
				Thread.sleep(1); //μΌμ‹œμ •μ§€λ˜λ©΄ InterruptedException λ°œμƒ 
			}
		} catch (InterruptedException e) {
			System.out.println("InterruptedException μ˜ˆμ™Έκ°€ λ°œμƒν•˜μ˜€μŠ΅λ‹ˆλ‹€");
			e.printStackTrace();
		}
	System.out.println("μ‹€ν–‰μ’…λ£Œ"); 
	}
}