π νλ‘μΈμ€μ μ°λ λ
νλ‘μΈμ€λ 'μ€νμ€μΈ νλ‘κ·Έλ¨'μ λ§νλ€. μ°λ¦¬κ° νλ‘κ·Έλ¨μ μ€νμν€λ©΄ OS(μλμ°, Mac λ±)λ νλ‘κ·Έλ¨ μ€νμ νμν λ°μ΄ν°μ λ©λͺ¨λ¦¬ λ±μ μμμ ν λΉνλ€. νλ‘μΈμ€λ μ΄λ κ² ν λΉ λ°μ μμκ³Ό μ°λ λλ‘ κ΅¬μ±λμ΄ μλ€.
μ°λ λλ 'νλ‘μΈμ€κ° ν λΉ λ°μ μμμ νμ©νμ¬ μ€μ μμ μ μ΄ννλ μ‘΄μ¬' λ₯Ό λ§νλ€. μ°λ λμ μμ±μλ μ νμ΄ μμ§λ§, μμ μ μννκΈ° μν λ©λͺ¨λ¦¬ 곡κ°μ νμλ‘ νλ€. μ°λ λλ νλ‘μΈμ€κ° κ°μ§κ³ μλ μμμ ν λΉλ°κΈ° λλ¬Έμ νλ‘μΈμ€μ λ©λͺ¨λ¦¬ νκ³μΉκΉμ§λ§ μμ±ν μ μλ€.
π λ©ν° νμ€νΉκ³Ό λ©ν° μ°λ λ©
μ°λ¦¬λ λ¬Έμ μμ μ νλ©΄μ λμμ μ νλΈ μμ μ κ°μν μ μλ€. μ΄λ μλμ°μ κ°μ μ΄μ체μ λ λ©ν°νμ€νΉμ μ 곡νκΈ° λλ¬Έμ κ°λ₯ν μΌμ΄λ€. λ©ν° νμ€νΉμ λ κ°μ§ μ΄μμ μμ μ λμμ νλ κ²μ μλ―Ένλ©°, νλ‘μΈμ€ + νλ‘μΈμ€ μ‘°ν© λΏλ§ μλλΌ ν νλ‘μΈμ€μμ μμ 1 + μμ 2λ₯Ό μλ―Έν μ μλ€.
μμ μ μννλ CPUμ μ½μ΄λ ν λ²μ λ¨ νλμ μμ λ§ μνν μ μλ€. μλ₯Ό λ€μ΄ λ¬Έμ μμ μ νλ©΄μ μ νλΈ μμ μ λμμ νλ €λ©΄ μ΅μ λ κ°μ μ½μ΄κ° νμνλ€. μ°λ¦¬λ λ¬Έμ μμ λνκ³ μμ λ κ°μνκ³ λ©μ μ μμ λ¬Έμλ₯Ό 보λ΄λ©΄μ νμΌμ λ€μ΄λ‘λνκΈ°λ νλ€. μ΄λ κ² ν νλ‘μΈμ€μμμ μ΄λ£¨μ΄μ§λ μμ μ μ²λ¦¬νκΈ° μν΄ μ½μ΄λ₯Ό μ¬μ©νλ€λ©΄ νλ‘κ·Έλ¨μ λͺ κ° μ€ννμ§ λͺ»ν κ²μ΄λ€.
μ΄λ₯Ό ν΄κ²°νκΈ° μν΄ λ©ν° μ°λ λ©μ μ΄μ©ν μ μλ€. λ©ν° μ°λ λ©μ μ¬λ¬ κ°μ μ°λ λκ° λ²κ°μκ°λ©° μ€νλλ κ²μ²λΌ 보μ΄κ² νλ κΈ°μ λ‘ μ½μ΄λ λ§€μ° λΉ λ₯Έ μλλ‘ μ°λ λλ₯Ό μ ννλ©΄μ κ° μ°λ λμκ² μμ μ ν λΉνλ€.
ποΈ μλ μ κ² - λ©ν° μ°λ λ©
λ©ν° μ°λ λ©μ λ€μκ³Ό κ°μ μ₯μ μ΄ μμ΄ λ§μ΄ μ¬μ©λλ€.
- CPUμ μ¬μ©λ₯ μ΄ μ¦κ°νλ€.
- μμμ λ³΄λ€ ν¨μ¨μ μΌλ‘ μ¬μ©ν μ μλ€.
- μ¬μ©μμ μμ²μ λΉ λ₯΄κ² μλ΅ν μ μλ€.
νμ§λ§ λ©ν° μ°λ λ©μ μ¬λ¬ μ°λ λκ° κ°μ νλ‘μΈμ€ λ΄μμ μμμ 곡μ νλ©΄μ μμ νκΈ° λλ¬Έμ λκΈ°ν, κ΅μ°©μνμ κ°μ λ¬Έμ κ° μκΈΈ μ μλ€.
π μ°λ λμ ꡬνκ³Ό μ€ν
μ°λ λλ₯Ό ꡬννλ λ°©λ²μλ Thread.classλ₯Ό μμνλ λ°©λ²κ³Ό Runnable μΈν°νμ΄μ€λ₯Ό ꡬννλ λ°©λ²μ΄ μλ€. λ κ°μ§ λ°©λ² λͺ¨λ run() λ©μλλ₯Ό μ€λ²λΌμ΄λ©νμ¬ λͺΈμ²΄λ₯Ό μμ±νλ©΄ λλ€.
ποΈ Thread ν΄λμ€
Thread ν΄λμ€λ Threadλ₯Ό μμν μμ μΈμ€ν΄μ€λ₯Ό μμ±ν λ€ start() λ©μλλ₯Ό μ΄μ©ν΄ μ€νμν¬ μ μλ€.
class ThreadEx extends Thread {
public void run() { ... }
}
class ThreadMain {
public static void main(String[] args) {
ThreadEx t = new ThreadEx();
t.start();
}
}
ποΈ Runnable μΈν°νμ΄μ€
Runnable μΈν°νμ΄μ€μ κ²½μ° Runnableμ μμν μμ μΈμ€ν΄μ€λ₯Ό μμν λ€μ Thread(Runnable target) μμ±μλ‘ Threadλ₯Ό μμ±νλ©΄ λλ€.
public class ThreadEx2 implement Runnable {
public void run() { ... }
}
public class ThreadMain {
public static void main(String[] args) {
Runnable r = new ThreadEx2();
Thread t = new Thread(r);
t.start();
}
}
ποΈ Runnableμ΄ μ νΈλλ μ΄μ
Thread ν΄λμ€κ° java.lang.Thread ν΄λμ€λ§ λ€λ£¨κΈ° λλ¬Έμ λ μ¬μ보μ΄μ§λ§ Runnableμ΄ λ λ§μ΄ μ¬μ©λκ³ μλ€. μ΄μ λ λ€μκ³Ό κ°λ€.
- μλ°λ λ€μ€ μμμ μ§μνμ§ μλλ€. λ°λΌμ Threadλ₯Ό μ¬μ©νλ€λ κ²μ λ€λ₯Έ ν΄λμ€λ₯Ό μμν μ μμμ μλ―ΈνκΈ°λ νλ€.
- Runnable μΈν°νμ΄μ€λ Thread λλ Executors λ±μ μν΄ μ€νλ μ μκΈ° λλ¬Έμ Runnableμ μ¬μ©νλ κ²μ΄ μ’μ λμμΈ κ²°μ μ΄λ€.
- Runnableλ‘ μμ μ λΆλ¦¬νλ€λ κ²μ κ·Έ μμ μ μ¬μ¬μ©ν μ μμΌλ©° λ€λ₯Έ μ€νμμ μν΄ μ€νλ μ μμμ μλ―Ένλ€.
ποΈ μΈμ Threadμ μ¬μ©ν΄μΌ νλκ°?
- OOPμμ ν΄λμ€λ₯Ό μμνλ€λ κ²μ μλ‘μ΄ κΈ°λ₯μ μΆκ°νκ±°λ, κ°μ λ° μμ νλ€λ κ²μ μλ―Ένλ€. λ°λΌμ Threadμμ μ΄λ ν κΈ°λ₯ μΆκ°λ μμ μ νμ§ μλλ€λ©΄ Runnable μΈν°νμ΄μ€λ₯Ό μ¬μ©νμ.
ποΈ start() λ©μλ
μ°λ λλ₯Ό μμ±ν λ€μλ start() λ©μλλ₯Ό νΈμΆνμ¬ μ€νμμΌμ€μΌ νλ€. start() λ©μλκ° νΈμΆλλ©΄ μ€νλκΈ° μνμ μλ€κ° μμ μ μνκ° λλ©΄ μ€νλλ€. λ start()λ ν λ²λ§ νΈμΆλ μ μλ€.
ν κ°μ§ μ΄μν μ μ ThreadEx ν΄λμ€λ Threadλ₯Ό μμνκ³ run() λ©μλλ₯Ό μ€λ²λΌμ΄λ© νλ€. κ·Έλ°λ° μ°λ λλ₯Ό μ€νμν€κΈ° μν΄ νΈμΆνλ λ©μλλ start()μ΄λ€. start() λ©μλμλ native λ©μλλ‘ μ°λ λμ μμ μ μ€ννλ€. native λ©μλλ μλ‘μ΄ μ°λ λκ° μμ μ μ€ννλλ° νμν νΈμΆμ€νμ μμ±ν λ€μ run() λ©μλλ₯Ό μ€ννλ€.
run() λ©μλλ₯Ό νΈμΆνλ©΄ νΈμΆ μ€νμ΄ μμ±λμ§ μκ³ λ©μλλ§ νΈμΆλλ©°, start() λ©μλλ νΈμΆμ€νμ μμ±ν λ€μ run() λ©μλλ₯Ό μ€ννλ€.
π μ±κΈ μ°λ λμ λ©ν° μ°λ λ
νλμ μ°λ λλ‘ λ κ°μ μμ μ νλ κ²½μ° P1μ λ§μΉ νμ P2μ μμ μ μμνλ€. λ κ°μ μ°λ λλ‘ λ κ°μ μμ μ νλ κ²½μ° μ§§μ μκ°λμ λ κ°μ μ°λ λκ° λ²κ°μ κ°λ©΄μ μνλλ€.
λ¨μ μ°μ°μ κ²½μ° λ¨μΌ μ°λ λμ μμ μ΄ μ€λ걸리기λ νλ€. μ΄λ μ°λ λκ°μ 컨ν μ€νΈ μ€μμΉμ΄ λ°μνκΈ° λλ¬Έμ΄λ€. 컨ν μ€νΈ μ€μμΉμ΄λ λ€μμ μ€νν΄μΌν μμΉ λ±μ μ 보λ₯Ό μ μ₯νκ³ μ½μ΄ μ€λ κ³Όμ μ μλ―Ένλ€. λ©ν° μ½μ΄μμ λ©ν° μ°λ λλ₯Ό μ¬μ©νλ κ²½μ°μλ μμμ κΈ°λ€λ¦¬λ μκ°μ΄ μκΈΈ μ μλ€. μλ₯Ό λ€μ΄ ν μ°λ λκ° νλ©΄μ μΆλ ₯νκ³ μλ λμ λ€λ₯Έ μ°λ λλ μΆλ ₯μ΄ λλκΈ°λ₯Ό κΈ°λ€λ €μΌ νλ€.
λ μ°λ λκ° μλ‘ λ€λ₯Έ μμμ μ¬μ©νλ κ²½μ°μλ λ©ν° μ°λ λκ° λ ν¨μ¨μ μ΄λ€. μλ₯Ό λ€λ©΄ μ¬μ©μλ‘λΆν° λ°μ΄ν°λ₯Ό μ λ ₯λ°λ μμ , λ€νΈμν¬λ‘ νμΌμ μ£Όκ³ λ°λ μμ λ±μ΄ ν΄λΉλλ€.
π μ°λ λμ μ°μ μμ
setPriority(int priority), getPriority()λ₯Ό μ΄μ©νμ¬ μ°λ λμ μ°μ μμλ₯Ό μ§μ νκ±°λ νμΈν μ μλ€. μ°μ μμ λ²μλ 1 ~ 10μ΄λ©° μ«μκ° λμμλ‘ μ°μ μμκ° λλ€.
λ©ν°μ½μ΄μμλ μ°λ λμ μ°μ μμμ λ°λ₯Έ μ°¨μ΄κ° κ±°μ μμΌλ©°, OSλ§λ€ λ€λ₯Έ λ°©μμΌλ‘ μ€μΌμ₯΄λ§ νκΈ° λλ¬Έμ κ²°κ³Όκ° λ¬λΌμ§ μ μλ€. λ°λΌμ μ°λ λμ μ°μ μμλ₯Ό λΆμ¬νκΈ°λ³΄λ€ μ°μ μμλ₯Ό PriorityQueueμ μ μ₯ν΄ λκ³ , μ°μ μμκ° λμ μμ μ΄ λ¨Όμ μ²λ¦¬λλλ‘ νλ κ²μ΄ μ’λ€.
π λ°λͺ¬ μ°λ λ
λ°λͺ¬ μ°λ λλ μΌλ° μ°λ λμ μμ μ λλ 보쑰 μ°λ λμ΄λ€. μλ₯Ό λ€μ΄ λ¬Έμ νλ‘κ·Έλ¨μ μλμ μ₯, νλ©΄μλκ°±μ λ±μ΄ μλ€. κΈ°λ³Έμ μΌλ‘ ꡬνμ 무ν루νμ 쑰건문μ μ΄μ©ν΄μ μ€ν ν λκΈ°νκ³ μλ€κ° νΉμ μ‘°κ±΄μ΄ λ§μ‘±λλ©΄ μμ μ μννκ³ λ€μ λκΈ°νλλ‘ μμ±νλ€. λ°λͺ¬ μ°λ λλ μ€ννκΈ° μ μ setDaemon(true)λ₯Ό νΈμΆν΄μΌ νλ€.
public class DaemonThreadExample {
public static void main(String[] args) {
MyThread myThread = new MyThread();
myThread.setDaemon(true);
myThread.start();
// λ©μΈ μ€λ λ μ€ν μ€
try {
Thread.sleep(3000); // 3μ΄κ° λκΈ°
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("λ©μΈ μ€λ λ μ’
λ£");
}
}
class MyThread extends Thread {
public void run() {
while (true) {
System.out.println("λ°λͺ¬ μ€λ λ μ€ν μ€");
try {
Thread.sleep(1000); // 1μ΄κ° λκΈ°
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
π μ°λ λμ μ€νμ μ΄
μ°λ λμ μ€νμ μ μ΄νλ sleep(), join(), interrupt(), suspend(), resume(), yield()μ λν΄ μμ보μ.
ποΈ μ°λ λμ μν κ·Έλν
- μ°λ λλ₯Ό μμ±νκ³ μ€ννμ§ μμ μνλ₯Ό NEWλΌκ³ νλ©°, start() λ©μλλ₯Ό νΈμΆνλ©΄ μ€ν λκΈ°(Runnable) μνκ° λλ€.
- μ€ν λκΈ° μνμμ μ°¨λ‘λλ‘ μ€νμ΄ λλ€.
- μ£Όμ΄μ§ μ€νμκ°μ΄ λ€ λκ±°λ yield()κ° νΈμΆλλ©΄ λ€μ μ€ν λκΈ°μνκ° λλ€.
- μ€ν μ€μ suspend(), sleep(), wait(), join(), I/O blockμ μν΄ μΌμμ μ§μνκ° λ μ μλ€.
- μΌμμ μ§μκ°μ΄ λ€λκ±°λ notify(), resume(), interrupt() λ©μλκ° νΈμΆλλ©΄ λ€μ μ€νλκΈ° μνκ° λλ€.
- μ€νμ λͺ¨λ λ§μΉλ©΄ μλ©Έ(TERMINATED) λλ€.
ποΈ sleep() λ©μλ
sleep()μ μ§μ λ μκ°λμ μ°λ λλ₯Ό λ©μΆκ² νλ€. sleep()μ μν΄ μΌμμ μ§ μνκ° λ μ°λ λλ μ§μ λ μκ°μ΄ λ€ λκ±°λ interrupt()κ° νΈμΆλλ©΄ InterruptedExceptionμ΄ λ°μνκ³ , μ€νλκΈ° μνκ° λλ€. λ°λΌμ sleep()μ νΈμΆν λλ νμ try-catchλ¬ΈμΌλ‘ μμΈλ₯Ό μ²λ¦¬ν΄μ€μΌ νλ€.
void delay(long millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e ) {}
}
sleep()μ νμ νμ¬ μ€ν μ€μΈ μ°λ λμ λν΄ μλνκΈ° λλ¬Έμ μ°Έμ‘°λ³μκ° μλ "Thread.sleep()" λ€μκ³Ό κ°μ΄ μ€νν± λ©μλλ₯Ό μ΄μ©ν΄μΌ νλ€.
ποΈ interrupt()μ interrupted()
μ§ν μ€μΈ μ°λ λλ₯Ό μμ μ΄ λλκΈ° μ μ μ·¨μνλ κ²½μ°(e.g μλ₯Ό λ€μ΄ νμΌμ λ€μ΄λ‘λ νλ€κ° μ€κ°μ μ·¨μνλ κ²½μ°)μλ interruptλ₯Ό μ΄μ©νμ¬ μμ μ μ·¨μν μ μλ€.
// μ°λ λμ interrupted μνλ₯Ό falseμμ trueλ‘ λ³κ²½νλ€.
void interrupt()
// μ°λ λμ interruptedμνλ₯Ό λ°ννλ€.
boolean isInterrupted
// νμ¬ μ°λ λμ interruptedμνλ₯Ό λ°ν ν, falseλ‘ λ³κ²½νλ€.
static boolean interrupted()
public class InterruptExample {
public static void main(String[] args) {
Thread myThread = new MyThread();
myThread.start();
try {
Thread.sleep(2000); // 2μ΄κ° λκΈ°
} catch (InterruptedException e) {
e.printStackTrace();
}
// μ€λ λ μΈν°λ½νΈ
myThread.interrupt();
}
}
class MyThread extends Thread {
public void run() {
while (!isInterrupted()) {
try {
System.out.println("μ€λ λ μ€ν μ€");
Thread.sleep(500); // 0.5μ΄κ° λκΈ°
} catch (InterruptedException e) {
System.out.println("μΈν°λ½νΈ λ°μ");
// μ€λ λ μΈν°λ½νΈ μνλ₯Ό 체ν¬νκ³ νμν μμ
μν
// μ: μμ μ 리, μ’
λ£ λ±
return; // μ€λ λ μ’
λ£
}
}
}
}
ποΈ suspend(), resume()
μμ μΈ λ©μλλ μ€λ λλ₯Ό μΌμ μ μ§μν€κ³ μ¬κ°μν€λ κΈ°λ₯μ μ 곡νμ§λ§ μ¬μ© μ κ΅μ°© μνμ μ€λ λ μΌκ΄μ± λ¬Έμ κ° λ°μν μ μλ€. λ°λΌμ κΆμ₯λμ§ μμΌλ©°, wait(), notify(), Lockκ³Ό κ°μ μ€λ λ λκΈ°ν λ©μ»€λμ¦μ μ¬μ©νλ κ²μ΄ μ’λ€.
ποΈ yield()
νμ¬ μ€ν μ€μΈ μ€λ λλ₯Ό μΌμμ μΌλ‘ μ μ§ μν€κ³ λ€λ₯Έ μ€λ λκ° μ€ν λλλ‘ μ보(yield)νλ€.
class MyThread extends Thread {
private String name;
public MyThread(String name) {
this.name = name;
}
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.println(name + ": " + i);
// μ€λ λ μ€ν μ€κ°μ λ€λ₯Έ μ€λ λμκ² μ€ν κΈ°νλ₯Ό μ보
Thread.yield();
}
}
}
public class Main {
public static void main(String[] args) {
MyThread thread1 = new MyThread("Thread 1");
MyThread thread2 = new MyThread("Thread 2");
thread1.start();
thread2.start();
}
}
μμ μ½λμμλ λ κ°μ μ°λ λκ° λ²κ°μκ°λ©° μ€νλλ κ²μ νμΈν μ μλ€.
ποΈ join()
νΈμΆν μ€λ λλ join() λ©μλλ₯Ό νΈμΆν μ€λ λκ° μ’ λ£λ λκΉμ§ λκΈ°νλ€.
public class JoinExample {
public static void main(String[] args) {
Thread thread1 = new Thread(new MyThread("Thread 1"));
Thread thread2 = new Thread(new MyThread("Thread 2"));
Thread thread3 = new Thread(new MyThread("Thread 3"));
thread1.start();
thread2.start();
thread3.start();
try {
thread1.join(); // thread1μ΄ μ’
λ£λ λκΉμ§ λκΈ°
thread2.join(); // thread2κ° μ’
λ£λ λκΉμ§ λκΈ°
thread3.join(); // thread3μ΄ μ’
λ£λ λκΉμ§ λκΈ°
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("λ©μΈ μ€λ λ μ’
λ£");
}
}
class MyThread implements Runnable {
private String name;
public MyThread(String name) {
this.name = name;
}
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.println(name + ": " + i);
try {
Thread.sleep(1000); // 1μ΄κ° λκΈ°
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
main λ©μλλ thread1,2,3κ° λͺ¨λ μμ°¨μ μΌλ‘ μ€νλκ³ μ’ λ£λ λκΉμ§ λκΈ°νκ² λλ€.