CodeGym/Java Blog/๋ฌด์ž‘์œ„์˜/๋” ๋‚˜์€ ์กฐํ•ฉ: Java์™€ Thread ํด๋ž˜์Šค. 6๋ถ€ โ€” ๋ฐœ์‚ฌ!
John Squirrels
๋ ˆ๋ฒจ 41
San Francisco

๋” ๋‚˜์€ ์กฐํ•ฉ: Java์™€ Thread ํด๋ž˜์Šค. 6๋ถ€ โ€” ๋ฐœ์‚ฌ!

๋ฌด์ž‘์œ„์˜ ๊ทธ๋ฃน์— ๊ฒŒ์‹œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค
ํšŒ์›

์†Œ๊ฐœ

์Šค๋ ˆ๋“œ๋Š” ํฅ๋ฏธ๋กœ์šด ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด์ „ ๋ฆฌ๋ทฐ์—์„œ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ์„ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋ช‡ ๊ฐ€์ง€ ๋„๊ตฌ๋ฅผ ์‚ดํŽด๋ณด์•˜์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๊ฐ€ ํ•  ์ˆ˜ ์žˆ๋Š” ๋‹ค๋ฅธ ํฅ๋ฏธ๋กœ์šด ์ผ์ด ๋ฌด์—‡์ธ์ง€ ๋ด…์‹œ๋‹ค. ์ด ์‹œ์ ์—์„œ ์šฐ๋ฆฌ๋Š” ๋งŽ์€ ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด " Better together: Java and the Thread class. Part I โ€” Threads of execution "์—์„œ ์šฐ๋ฆฌ๋Š” Thread ํด๋ž˜์Šค๊ฐ€ ์‹คํ–‰ ์Šค๋ ˆ๋“œ๋ฅผ ๋‚˜ํƒ€๋‚ธ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์Šค๋ ˆ๋“œ๊ฐ€ ์–ด๋–ค ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ž‘์—…์—์„œ ๋ฅผ ์ˆ˜ํ–‰ํ•˜๋ ค๋ฉด run์Šค๋ ˆ๋“œ๋ฅผ ๋กœ ํ‘œ์‹œํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค Runnable. ๊ธฐ์–ตํ•˜๊ธฐ ์œ„ํ•ด Tutorialspoint Online Java Compiler๋ฅผ๋” ๋‚˜์€ ์กฐํ•ฉ: Java์™€ Thread ํด๋ž˜์Šค.  6๋ถ€ โ€” ๋ฐœ์‚ฌ!  - 1 ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค .
public static void main(String[] args){
	Runnable task = () -> {
 		Thread thread = Thread.currentThread();
		System.out.println("Hello from " + thread.getName());
	};
	Thread thread = new Thread(task);
	thread.start();
}
๋˜ํ•œ ์ž๋ฌผ์‡ ๋ผ๋Š” ๊ฒƒ์ด ์žˆ๋‹ค๋Š” ๊ฒƒ๋„ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. " Better together: Java and the Thread class. Part II โ€” Synchronization ์—์„œ ์ด์— ๋Œ€ํ•ด ๋ฐฐ์› ์Šต๋‹ˆ๋‹ค . ํ•œ ์Šค๋ ˆ๋“œ๊ฐ€ ์ž ๊ธˆ์„ ํš๋“ํ•˜๋ฉด ์ž ๊ธˆ์„ ํš๋“ํ•˜๋ ค๋Š” ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๋Š” ์ž ๊ธˆ์ด ํ•ด์ œ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ ค์•ผ ํ•ฉ๋‹ˆ๋‹ค.
import java.util.concurrent.locks.*;

public class HelloWorld{
	public static void main(String []args){
		Lock lock = new ReentrantLock();
		Runnable task = () -> {
			lock.lock();
			Thread thread = Thread.currentThread();
			System.out.println("Hello from " + thread.getName());
			lock.unlock();
		};
		Thread thread = new Thread(task);
		thread.start();
	}
}
์šฐ๋ฆฌ๊ฐ€ ํ•  ์ˆ˜ ์žˆ๋Š” ๋‹ค๋ฅธ ํฅ๋ฏธ๋กœ์šด ์ผ๋“ค์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•  ์‹œ๊ฐ„์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์„ธ๋งˆํฌ์–ด

๋™์‹œ์— ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ์Šค๋ ˆ๋“œ ์ˆ˜๋ฅผ ์ œ์–ดํ•˜๋Š” โ€‹โ€‹๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ๋ฐฉ๋ฒ•์€ ์„ธ๋งˆํฌ์–ด์ž…๋‹ˆ๋‹ค. ์ฒ ๋„ ์‹ ํ˜ธ์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๋…น์ƒ‰์€ ์ง„ํ–‰์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ๋นจ๊ฐ„์ƒ‰์€ ๋Œ€๊ธฐ๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์„ธ๋งˆํฌ์–ด์—์„œ ๋ฌด์—‡์„ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๊นŒ? ์ž…์žฅ. ์•ก์„ธ์Šค ๊ถŒํ•œ์„ ์–ป์œผ๋ ค๋ฉด ํš๋“ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์•ก์„ธ์Šค ๊ถŒํ•œ์ด ๋” ์ด์ƒ ํ•„์š”ํ•˜์ง€ ์•Š์œผ๋ฉด ์ด๋ฅผ ์ œ๊ณตํ•˜๊ฑฐ๋‚˜ ํ•ด์ œํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ๋ด…์‹œ๋‹ค. ํด๋ž˜์Šค ๋ฅผ ๊ฐ€์ ธ์™€์•ผ ํ•ฉ๋‹ˆ๋‹ค java.util.concurrent.Semaphore. ์˜ˆ:
public static void main(String[] args) throws InterruptedException {
	Semaphore semaphore = new Semaphore(0);
	Runnable task = () -> {
		try {
			semaphore.acquire();
			System.out.println("Finished");
			semaphore.release();
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	};
	new Thread(task).start();
	Thread.sleep(5000);
	semaphore.release(1);
}
๋ณด์‹œ๋‹ค์‹œํ”ผ ์ด๋Ÿฌํ•œ ์ž‘์—…(ํš๋“ ๋ฐ ํ•ด์ œ)์€ ์„ธ๋งˆํฌ์–ด์˜ ์ž‘๋™ ๋ฐฉ์‹์„ ์ดํ•ดํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค. ๊ฐ€์žฅ ์ค‘์š”ํ•œ ๊ฒƒ์€ ์•ก์„ธ์Šค ๊ถŒํ•œ์„ ์–ป์œผ๋ ค๋ฉด ์„ธ๋งˆํฌ์–ด์— ์–‘์ˆ˜ ํ—ˆ๊ฐ€๊ฐ€ ์žˆ์–ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด ๊ฐœ์ˆ˜๋Š” ์Œ์ˆ˜๋กœ ์ดˆ๊ธฐํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  1๊ฐœ ์ด์ƒ์˜ ํ—ˆ๊ฐ€์ฆ์„ ์š”์ฒญ(์ทจ๋“)ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

CountDownLatch

๋‹ค์Œ ๋ฉ”์ปค๋‹ˆ์ฆ˜์€ CountDownLatch. ๋‹น์—ฐํžˆ ์ด๊ฒƒ์€ ์นด์šดํŠธ๋‹ค์šด์ด ์žˆ๋Š” ๊ฑธ์‡ ์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ํด๋ž˜์Šค์— ๋Œ€ํ•œ ์ ์ ˆํ•œ import ๋ฌธ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค java.util.concurrent.CountDownLatch. ๋ชจ๋‘๊ฐ€ ์ถœ๋ฐœ์„ ์— ๋ชจ์ด๋Š” ๋‹ฌ๋ฆฌ๊ธฐ ๊ฒฝ์ฃผ์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋ชจ๋‘๊ฐ€ ์ค€๋น„๋˜๋ฉด ๋ชจ๋‘๊ฐ€ ๋™์‹œ์— ์ถœ๋ฐœ ์‹ ํ˜ธ๋ฅผ ๋ฐ›๊ณ  ๋™์‹œ์— ์ถœ๋ฐœํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ:
public static void main(String[] args) {
	CountDownLatch countDownLatch = new CountDownLatch(3);
	Runnable task = () -> {
		try {
			countDownLatch.countDown();
			System.out.println("Countdown: " + countDownLatch.getCount());
			countDownLatch.await();
			System.out.println("Finished");
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	};
	for (int i = 0; i < 3; i++) {
		new Thread(task).start();
 	}
}
๋จผ์ € ๋ž˜์น˜์— countDown(). Google์€ ์นด์šดํŠธ๋‹ค์šด์„ "0๊นŒ์ง€ ์—ญ์ˆœ์œผ๋กœ ์ˆซ์ž๋ฅผ ์„ธ๋Š” ํ–‰์œ„"๋ผ๊ณ  ์ •์˜ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ๋ž˜์น˜์— ์ง€์‹œํ•ฉ๋‹ˆ๋‹ค await(). ์ฆ‰, ์นด์šดํ„ฐ๊ฐ€ 0์ด ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ์‹ญ์‹œ์˜ค. ํฅ๋ฏธ๋กญ๊ฒŒ๋„ ์ด๊ฒƒ์€ ์ผํšŒ์„ฑ ์นด์šดํ„ฐ์ž…๋‹ˆ๋‹ค. Java ์„ค๋ช…์„œ์—๋Š” "์Šค๋ ˆ๋“œ๊ฐ€ ์ด๋Ÿฌํ•œ ๋ฐฉ์‹์œผ๋กœ ๋ฐ˜๋ณต์ ์œผ๋กœ ์นด์šดํŠธ ๋‹ค์šดํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ ๋Œ€์‹  CyclicBarrier๋ฅผ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค"๋ผ๊ณ  ๋‚˜์™€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰, ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์นด์šดํ„ฐ๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ ๋‹ค๋ฅธ ์˜ต์…˜์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค CyclicBarrier.

CyclicBarrier

์ด๋ฆ„์—์„œ ์•Œ ์ˆ˜ ์žˆ๋“ฏ์ด CyclicBarrier"์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ" ์žฅ๋ฒฝ์ž…๋‹ˆ๋‹ค. ํด๋ž˜์Šค ๋ฅผ ๊ฐ€์ ธ์™€์•ผ ํ•ฉ๋‹ˆ๋‹ค java.util.concurrent.CyclicBarrier. ์˜ˆ๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
public static void main(String[] args) throws InterruptedException {
	Runnable action = () -> System.out.println("On your mark!");
	CyclicBarrier barrier = new CyclicBarrier(3, action);
	Runnable task = () -> {
		try {
			barrier.await();
			System.out.println("Finished");
		} catch (BrokenBarrierException | InterruptedException e) {
			e.printStackTrace();
		}
	};
	System.out.println("Limit: " + barrier.getParties());
	for (int i = 0; i < 3; i++) {
		new Thread(task).start();
	}
}
๋ณด์‹œ๋‹ค์‹œํ”ผ ์Šค๋ ˆ๋“œ๋Š” await๋ฉ”์„œ๋“œ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ๋Œ€๊ธฐํ•ฉ๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ ์žฅ๋ฒฝ ๊ฐ’์ด ๊ฐ์†Œํ•ฉ๋‹ˆ๋‹ค. barrier.isBroken()์นด์šดํŠธ๋‹ค์šด์ด 0์— ๋„๋‹ฌํ•˜๋ฉด ์žฅ๋ฒฝ์ด ๊นจ์ง„( ) ๊ฒƒ์œผ๋กœ ๊ฐ„์ฃผ๋ฉ๋‹ˆ๋‹ค . ์žฅ๋ฒฝ์„ ์žฌ์„ค์ •ํ•˜๋ ค๋ฉด ์—†๋Š” reset()๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค .CountDownLatch

๊ตํ™˜๊ธฐ

๋‹ค์Œ ๋ฉ”์ปค๋‹ˆ์ฆ˜์€ Exchanger์ž…๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋งฅ๋ฝ์—์„œ Exchange๋Š” ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ๊ตํ™˜๋˜๊ฑฐ๋‚˜ ๊ตํ™˜๋˜๋Š” ๋™๊ธฐํ™” ์ง€์ ์ž…๋‹ˆ๋‹ค. ์˜ˆ์ƒ๋Œ€๋กœ an์€ Exchanger๊ตํ™˜ ๋˜๋Š” ์Šค์™‘์„ ์ˆ˜ํ–‰ํ•˜๋Š” ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค. ๊ฐ€์žฅ ๊ฐ„๋‹จํ•œ ์˜ˆ๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
public static void main(String[] args) {
	Exchanger<String> exchanger = new Exchanger<>();
	Runnable task = () -> {
		try {
			Thread thread = Thread.currentThread();
			String withThreadName = exchanger.exchange(thread.getName());
			System.out.println(thread.getName() + " exchanged with " + withThreadName);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	};
	new Thread(task).start();
	new Thread(task).start();
}
์—ฌ๊ธฐ์„œ ์šฐ๋ฆฌ๋Š” ๋‘ ๊ฐœ์˜ ์Šค๋ ˆ๋“œ๋ฅผ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋“ค ๊ฐ๊ฐ์€ ๊ตํ™˜ ๋ฐฉ๋ฒ•์„ ์‹คํ–‰ํ•˜๊ณ  ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๋„ ๊ตํ™˜ ๋ฐฉ๋ฒ•์„ ์‹คํ–‰ํ•˜๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์Šค๋ ˆ๋“œ๊ฐ€ ์ „๋‹ฌ๋œ ์ธ์ˆ˜๋ฅผ ๊ตํ™˜ํ•ฉ๋‹ˆ๋‹ค. ํฅ๋ฏธ๋กœ์šด. ๋ญ”๊ฐ€ ์ƒ๊ฐ๋‚˜์ง€ ์•Š๋‚˜์š”? SynchronousQueue์˜ ์ค‘์‹ฌ์— ์žˆ๋Š” ๋ฅผ ์—ฐ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค CachedThreadPool. ๋ช…ํ™•์„ฑ์„ ์œ„ํ•ด ๋‹ค์Œ ์˜ˆ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.
public static void main(String[] args) throws InterruptedException {
	SynchronousQueue<String> queue = new SynchronousQueue<>();
	Runnable task = () -> {
		try {
			System.out.println(queue.take());
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	};
	new Thread(task).start();
	queue.put("Message");
}
์ด ์˜ˆ๋Š” ์ƒˆ ์Šค๋ ˆ๋“œ๊ฐ€ ์‹œ์ž‘๋  ๋•Œ ๋Œ€๊ธฐ์—ด์ด ๋น„์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋Œ€๊ธฐํ•œ๋‹ค๋Š” ๊ฒƒ์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ ๋ฉ”์ธ ์Šค๋ ˆ๋“œ๋Š” "Message" ๋ฌธ์ž์—ด์„ ๋Œ€๊ธฐ์—ด์— ๋„ฃ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ์ด ๋ฌธ์ž์—ด์ด ๋Œ€๊ธฐ์—ด์—์„œ ์ˆ˜์‹ ๋  ๋•Œ๊นŒ์ง€ ์ค‘์ง€๋ฉ๋‹ˆ๋‹ค. ์ด ํ•ญ๋ชฉ์— ๋Œ€ํ•œ ์ž์„ธํ•œ ๋‚ด์šฉ์€ " SynchronousQueue vs Exchanger "๋ฅผ ์ฐธ์กฐํ•˜์‹ญ์‹œ์˜ค .

ํŽ˜์ด์ €

์šฐ๋ฆฌ๋Š” ๋งˆ์ง€๋ง‰์„ ์œ„ํ•ด ์ตœ์„ ์„ ๋‹คํ–ˆ์Šต๋‹ˆ๋‹ค โ€” Phaser. ํด๋ž˜์Šค ๋ฅผ ๊ฐ€์ ธ์™€์•ผ ํ•ฉ๋‹ˆ๋‹ค java.util.concurrent.Phaser. ๊ฐ„๋‹จํ•œ ์˜ˆ๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.
public static void main(String[] args) throws InterruptedException {
        Phaser phaser = new Phaser();
        // By calling the register method, we register the current (main) thread as a party
        phaser.register();
        System.out.println("Phasecount is " + phaser.getPhase());
        testPhaser(phaser);
        testPhaser(phaser);
        testPhaser(phaser);
        // After 3 seconds, we arrive at the barrier and deregister. Number of arrivals = number of registrations = start
        Thread.sleep(3000);
        phaser.arriveAndDeregister();
        System.out.println("Phasecount is " + phaser.getPhase());
    }

    private static void testPhaser(final Phaser phaser) {
        // We indicate that there will be a +1 party on the Phaser
        phaser.register();
        // Start a new thread
        new Thread(() -> {
            String name = Thread.currentThread().getName();
            System.out.println(name + " arrived");
            phaser.arriveAndAwaitAdvance(); // The threads register arrival at the phaser.
            System.out.println(name + " after passing barrier");
        }).start();
    }
์ด ์˜ˆ๋Š” ๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ Phaser๋“ฑ๋ก ์ˆ˜๊ฐ€ ์žฅ๋ฒฝ์— ๋„์ฐฉํ•œ ์ˆ˜์™€ ์ผ์น˜ํ•  ๋•Œ ์žฅ๋ฒฝ์ด ๊นจ์ง€๋Š” ๊ฒƒ์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค. ์ด GeeksforGeeks ๊ธฐ์‚ฌ๋ฅผPhaser ์ฝ์œผ๋ฉด ๋” ์นœ์ˆ™ํ•ด์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค .

์š”์•ฝ

์ด ์˜ˆ์ œ์—์„œ ์•Œ ์ˆ˜ ์žˆ๋“ฏ์ด ์Šค๋ ˆ๋“œ๋ฅผ ๋™๊ธฐํ™”ํ•˜๋Š” ๋ฐฉ๋ฒ•์—๋Š” ์—ฌ๋Ÿฌ ๊ฐ€์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด์ „์—๋Š” ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ์˜ ์ธก๋ฉด์„ ๊ธฐ์–ตํ•ด ๋ณด์•˜์Šต๋‹ˆ๋‹ค. ์ด ์‹œ๋ฆฌ์ฆˆ์˜ ์ด์ „ ๊ธฐ์‚ฌ๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค. ์–ด๋–ค ์‚ฌ๋žŒ๋“ค์€ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋”ฉ์œผ๋กœ ๊ฐ€๋Š” ๊ธธ์€ "Java Concurrency in Practice"๋ผ๋Š” ์ฑ…์—์„œ ์‹œ์ž‘๋œ๋‹ค๊ณ  ๋งํ•ฉ๋‹ˆ๋‹ค. 2006๋…„์— ์ถœ๊ฐ„๋˜์—ˆ์ง€๋งŒ ์‚ฌ๋žŒ๋“ค์€ ์ด ์ฑ…์ด ์ƒ๋‹นํžˆ ๊ธฐ์ดˆ์ ์ด๋ฉฐ ์˜ค๋Š˜๋‚ ์—๋„ ์—ฌ์ „ํžˆ ๊ด€๋ จ์ด ์žˆ๋‹ค๊ณ  ๋งํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์—ฌ๊ธฐ์—์„œ ํ† ๋ก ์„ ์ฝ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. "Java Concurrency In Practice"๋Š” ์—ฌ์ „ํžˆ ์œ ํšจํ•ฉ๋‹ˆ๊นŒ? . ํ† ๋ก ์˜ ๋งํฌ๋ฅผ ์ฝ๋Š” ๊ฒƒ๋„ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด The Well-Grounded Java Developer ๋ผ๋Š” ์ฑ…์— ๋Œ€ํ•œ ๋งํฌ๊ฐ€ ์žˆ์œผ๋ฉฐ ํŠนํžˆ 4์žฅ. ์ตœ์‹  ๋™์‹œ์„ฑ ์„ ์–ธ๊ธ‰ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค . ์ด ์ฃผ์ œ์— ๋Œ€ํ•œ ์ „์ฒด ๋ฆฌ๋ทฐ๋„ ์žˆ์Šต๋‹ˆ๋‹ค."Java Concurrency in Practice"๋Š” Java 8 ์‹œ๋Œ€์—๋„ ์—ฌ์ „ํžˆ ์œ ํšจํ•ฉ๋‹ˆ๊นŒ? ์ด ๊ธฐ์‚ฌ๋Š” ๋˜ํ•œ ์ด ์ฃผ์ œ๋ฅผ ์ง„์ •์œผ๋กœ ์ดํ•ดํ•˜๊ธฐ ์œ„ํ•ด ์ฝ์–ด์•ผ ํ•  ๋‹ค๋ฅธ ๋‚ด์šฉ์— ๋Œ€ํ•œ ์ œ์•ˆ๋„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฐ ๋‹ค์Œ OCA/OCP Java SE 8 Programmer Practice Tests ์™€ ๊ฐ™์€ ํ›Œ๋ฅญํ•œ ์ฑ…์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค . ๋‘ ๋ฒˆ์งธ ์•ฝ์–ด์ธ OCP(Oracle Certified Professional)์— ๊ด€์‹ฌ์ด ์žˆ์Šต๋‹ˆ๋‹ค. "20์žฅ: Java ๋™์‹œ์„ฑ"์—์„œ ํ…Œ์ŠคํŠธ๋ฅผ ์ฐพ์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด ์ฑ…์—๋Š” ์งˆ๋ฌธ๊ณผ ๋‹ต๋ณ€์ด ํ•จ๊ป˜ ์„ค๋ช…๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ: ๋” ๋‚˜์€ ์กฐํ•ฉ: Java์™€ Thread ํด๋ž˜์Šค.  6๋ถ€ โ€” ๋ฐœ์‚ฌ!  - ์‚ผ๋งŽ์€ ์‚ฌ๋žŒ๋“ค์ด ์ด ์งˆ๋ฌธ์ด ๋ฐฉ๋ฒ• ์•”๊ธฐ์˜ ๋˜ ๋‹ค๋ฅธ ์˜ˆ๋ผ๊ณ  ๋งํ•˜๊ธฐ ์‹œ์ž‘ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•œํŽธ์œผ๋กœ๋Š” ๊ทธ๋ ‡์Šต๋‹ˆ๋‹ค. ๋ฐ˜๋ฉด ์— ExecutorService. Executor๊ทธ๋ฆฌ๊ณ ExecutorRunnable์Šค๋ ˆ๋“œ๊ฐ€ ์ƒ์„ฑ๋˜๋Š” ๋ฐฉ์‹์„ ๋‹จ์ˆœํžˆ ์ˆจ๊ธฐ๊ธฐ ์œ„ํ•œ ๊ฒƒ์ด์ง€๋งŒ ์Šค๋ ˆ๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ์ฃผ์š” ๋ฐฉ๋ฒ•, ์ฆ‰ ์ƒˆ ์Šค๋ ˆ๋“œ์—์„œ ๊ฐœ์ฒด๋ฅผ ์‹œ์ž‘ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ์•„๋‹™๋‹ˆ๋‹ค . ์ด๊ฒƒ์ด ์—†๋Š” ์ด์œ ์ž…๋‹ˆ๋‹ค . execute(Callable)์—์„œ ๊ฐ์ฒด ๋ฅผ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ๋‹จ์ˆœํžˆ ์ถ”๊ฐ€ํ•˜๊ธฐ ๋•Œ๋ฌธ ์ž…๋‹ˆ๋‹ค. ๋ฌผ๋ก  ๋ฉ”์„œ๋“œ ๋ชฉ๋ก์„ ์™ธ์šธ ์ˆ˜๋„ ์žˆ์ง€๋งŒ ํด๋ž˜์Šค ์ž์ฒด์˜ ํŠน์„ฑ์— ๋Œ€ํ•œ ์ง€์‹์„ ๋ฐ”ํƒ•์œผ๋กœ ๋‹ต์„ ๋งŒ๋“œ๋Š” ๊ฒƒ์ด ํ›จ์”ฌ ์‰ฝ์Šต๋‹ˆ๋‹ค. ๋‹ค์Œ์€ ์ฃผ์ œ์— ๋Œ€ํ•œ ๋ช‡ ๊ฐ€์ง€ ์ถ”๊ฐ€ ์ž๋ฃŒ์ž…๋‹ˆ๋‹ค. ExecutorServiceExecutorsubmit()Future ๋” ๋‚˜์€ ์กฐํ•ฉ: Java์™€ Thread ํด๋ž˜์Šค. 1๋ถ€ โ€” ์‹คํ–‰ ์Šค๋ ˆ๋“œ Java์™€ Thread ํด๋ž˜์Šค๋ฅผ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋ฉด ๋” ์ข‹์Šต๋‹ˆ๋‹ค. 2๋ถ€ โ€” ๋™๊ธฐํ™” ํ•จ๊ป˜ ํ•˜๋ฉด ๋” ์ข‹์Šต๋‹ˆ๋‹ค: Java์™€ Thread ํด๋ž˜์Šค. 3๋ถ€ โ€” ์ƒํ˜ธ ์ž‘์šฉ ๋” ๋‚˜์€ ์กฐํ•ฉ: Java์™€ Thread ํด๋ž˜์Šค. 4๋ถ€ โ€” ํ˜ธ์ถœ ๊ฐ€๋Šฅ, ๋ฏธ๋ž˜ ๋ฐ ์นœ๊ตฌ ๋” ๋‚˜์€ ์กฐํ•ฉ: Java ๋ฐ Thread ํด๋ž˜์Šค. ํŒŒํŠธ V โ€” ์ง‘ํ–‰์ž, ThreadPool, ํฌํฌ/์กฐ์ธ
์ฝ”๋ฉ˜ํŠธ
  • ์ธ๊ธฐ
  • ์‹ ๊ทœ
  • ์ด์ „
์ฝ”๋ฉ˜ํŠธ๋ฅผ ๋‚จ๊ธฐ๋ ค๋ฉด ๋กœ๊ทธ์ธ ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค
์ด ํŽ˜์ด์ง€์—๋Š” ์•„์ง ์ฝ”๋ฉ˜ํŠธ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค