์๊ฐ
์ค๋ ๋๋ ํฅ๋ฏธ๋ก์ด ๊ฒ์
๋๋ค. ์ด์ ๋ฆฌ๋ทฐ์์ ๋ฉํฐ์ค๋ ๋ฉ์ ๊ตฌํํ๋ ๋ฐ ์ฌ์ฉํ ์ ์๋ ๋ช ๊ฐ์ง ๋๊ตฌ๋ฅผ ์ดํด๋ณด์์ต๋๋ค. ์ฐ๋ฆฌ๊ฐ ํ ์ ์๋ ๋ค๋ฅธ ํฅ๋ฏธ๋ก์ด ์ผ์ด ๋ฌด์์ธ์ง ๋ด
์๋ค. ์ด ์์ ์์ ์ฐ๋ฆฌ๋ ๋ง์ ๊ฒ์ ์๊ณ ์์ต๋๋ค. ์๋ฅผ ๋ค์ด "
Better together: Java and the Thread class. Part I โ Threads of execution "์์ ์ฐ๋ฆฌ๋ Thread ํด๋์ค๊ฐ ์คํ ์ค๋ ๋๋ฅผ ๋ํ๋ธ๋ค๋ ๊ฒ์ ์๊ณ ์์ต๋๋ค. ์ค๋ ๋๊ฐ ์ด๋ค ์์
์ ์ํํ๋ค๋ ๊ฒ์ ์๊ณ ์์ต๋๋ค. ์์
์์ ๋ฅผ ์ํํ๋ ค๋ฉด
run
์ค๋ ๋๋ฅผ ๋ก ํ์ํด์ผ ํฉ๋๋ค
Runnable
.
๊ธฐ์ตํ๊ธฐ ์ํด Tutorialspoint Online Java Compiler๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค .
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();
phaser.register();
System.out.println("Phasecount is " + phaser.getPhase());
testPhaser(phaser);
testPhaser(phaser);
testPhaser(phaser);
Thread.sleep(3000);
phaser.arriveAndDeregister();
System.out.println("Phasecount is " + phaser.getPhase());
}
private static void testPhaser(final Phaser phaser) {
phaser.register();
new Thread(() -> {
String name = Thread.currentThread().getName();
System.out.println(name + " arrived");
phaser.arriveAndAwaitAdvance();
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 ๋์์ฑ"์์ ํ
์คํธ๋ฅผ ์ฐพ์ ์ ์์ต๋๋ค. ์ด ์ฑ
์๋ ์ง๋ฌธ๊ณผ ๋ต๋ณ์ด ํจ๊ป ์ค๋ช
๋์ด ์์ต๋๋ค. ์:
๋ง์ ์ฌ๋๋ค์ด ์ด ์ง๋ฌธ์ด ๋ฐฉ๋ฒ ์๊ธฐ์ ๋ ๋ค๋ฅธ ์๋ผ๊ณ ๋งํ๊ธฐ ์์ํ ์ ์์ต๋๋ค. ํํธ์ผ๋ก๋ ๊ทธ๋ ์ต๋๋ค. ๋ฐ๋ฉด ์
ExecutorService
.
Executor
๊ทธ๋ฆฌ๊ณ
Executor
Runnable
์ค๋ ๋๊ฐ ์์ฑ๋๋ ๋ฐฉ์์ ๋จ์ํ ์จ๊ธฐ๊ธฐ ์ํ ๊ฒ์ด์ง๋ง ์ค๋ ๋๋ฅผ ์คํํ๋ ์ฃผ์ ๋ฐฉ๋ฒ, ์ฆ ์ ์ค๋ ๋์์ ๊ฐ์ฒด๋ฅผ ์์ํ๋ ๋ฐฉ๋ฒ์ ์๋๋๋ค . ์ด๊ฒ์ด ์๋ ์ด์ ์
๋๋ค .
execute(Callable)
์์ ๊ฐ์ฒด ๋ฅผ ๋ฐํํ ์ ์๋ ๋ฉ์๋๋ฅผ ๋จ์ํ ์ถ๊ฐํ๊ธฐ ๋๋ฌธ ์
๋๋ค. ๋ฌผ๋ก ๋ฉ์๋ ๋ชฉ๋ก์ ์ธ์ธ ์๋ ์์ง๋ง ํด๋์ค ์์ฒด์ ํน์ฑ์ ๋ํ ์ง์์ ๋ฐํ์ผ๋ก ๋ต์ ๋ง๋๋ ๊ฒ์ด ํจ์ฌ ์ฝ์ต๋๋ค. ๋ค์์ ์ฃผ์ ์ ๋ํ ๋ช ๊ฐ์ง ์ถ๊ฐ ์๋ฃ์
๋๋ค.
ExecutorService
Executor
submit()
Future
๋ ๋์ ์กฐํฉ: Java์ Thread ํด๋์ค. 1๋ถ โ ์คํ ์ค๋ ๋ Java์ Thread ํด๋์ค๋ฅผ ํจ๊ป ์ฌ์ฉํ๋ฉด ๋ ์ข์ต๋๋ค. 2๋ถ โ ๋๊ธฐํ ํจ๊ป ํ๋ฉด ๋ ์ข์ต๋๋ค: Java์ Thread ํด๋์ค. 3๋ถ โ ์ํธ ์์ฉ ๋ ๋์ ์กฐํฉ: Java์ Thread ํด๋์ค. 4๋ถ โ ํธ์ถ ๊ฐ๋ฅ, ๋ฏธ๋ ๋ฐ ์น๊ตฌ ๋ ๋์ ์กฐํฉ: Java ๋ฐ Thread ํด๋์ค. ํํธ V โ ์งํ์, ThreadPool, ํฌํฌ/์กฐ์ธ