Contents

[Java Fundamental] Multi Thread

์ž๋ฐ” ๊ธฐ๋ณธ ์žŠ์ง€ ์•Š๊ฒŒ ์ •๋ฆฌํ•˜๊ธฐ! ๐Ÿค”

ํ”„๋กœ์„ธ์Šค์™€ ์Šค๋ ˆ๋“œ

  • ํ”„๋กœ์„ธ์Šค(process) : ์šด์˜์ฒด์ œ์—์„œ ์‹คํ–‰ ์ค‘์ธ ํ•˜๋‚˜์˜ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์„ ์˜๋ฏธ
  • ๋ฉ€ํ‹ฐ ํƒœ์Šคํ‚น(multi tasking)
    • ์šด์˜ ์ฒด์ œ์—์„œ ๋‘ ๊ฐ€์ง€ ์ด์ƒ์˜ ๋‹ค์ค‘ ์ž‘์—…(ํ”„๋กœ์„ธ์Šค)๋ฅผ ๋™์‹œ์— ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธ.
    • ์šด์˜ ์ฒด์ œ์—์„œ๋Š” ๋ฉ€ํ‹ฐ ํƒœ์Šคํ‚น์„ ํ•  ์ˆ˜ ์žˆ๋„๋ก CPU ๋ฐ ๋ฉ”๋ชจ๋ฆฌ ์ž์›์„ ์ ์ ˆํžˆ ํ• ๋‹นํ•˜๊ณ  ๋ณ‘๋ ฌ๋กœ ์‹คํ–‰์‹œํ‚จ๋‹ค. ํ• ๋‹น๋ฐ›์€ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ฐ€์ง€๊ณ  ์‹คํ–‰ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋…๋ฆฝ์ ์ด๋‹ค.

๋ฉ”์ธ ์Šค๋ ˆ๋“œ

  • ์ž๋ฐ” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์€ ๋ฉ”์ธ ์Šค๋ ˆ๋“œ(main thread)๊ฐ€ main() ๋ฉ”์†Œ๋“œ๋ฅผ ์‹คํ–‰ ํ•˜๋ฉด์„œ ์‹œ์ž‘.
  • ๋ฉ”์ธ ์Šค๋ ˆ๋“œ๋Š” ํ•„์š”์— ๋”ฐ๋ผ ์ž‘์—… ์Šค๋ ˆ๋“œ๋ฅผ ๋งŒ๋“ค์–ด ๋ณ‘๋ ฌ๋กœ ์‹คํ–‰ ๊ฐ€๋Šฅํ•˜๋‹ค.
  • ์‹ฑ๊ธ€ ์Šค๋ ˆ๋“œ์—์„œ๋Š” ๋ฉ”์ธ ์Šค๋ ˆ๋“œ๊ฐ€ ์ข…๋ฃŒ๋˜๋ฉด ํ”„๋กœ์„ธ์Šค๊ฐ€ ์ข…๋ฃŒ๋˜์ง€๋งŒ, ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋“œ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜์—์„œ๋Š” ์‹คํ–‰ ์ค‘์ธ ์Šค๋ ˆ๋“œ๊ฐ€ ํ•˜๋‚˜๋ผ๋„ ์žˆ๋‹ค๋ฉด ํ”„๋กœ์„ธ์Šค๋Š” ์ข…๋ฃŒ๋˜์ง€ ์•Š๋Š”๋‹ค.

์ž‘์—… ์Šค๋ ˆ๋“œ ์ƒ์„ฑ๊ณผ ์‹คํ–‰

  • ์ž๋ฐ”์—์„œ๋Š” ์Šค๋ ˆ๋“œ๋„ ๊ฐ์ฒด(ํด๋ž˜์Šค)๋กœ ์ƒ์„ฑ๋œ๋‹ค.

implements runnable

  • Runnable : ์ž‘์—… ์Šค๋ ˆ๋“œ๊ฐ€ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ์ฝ”๋“œ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ๋Š” ๊ฐ์ฒด
  • ์ธํ„ฐํŽ˜์ด์Šค ํƒ€์ž…์ด๋ฏ€๋กœ run()์„ ์žฌ์ •์˜ํ•˜์—ฌ ์‹คํ–‰ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑ
1
Thread thread = new Thread(Runnable target);
  • start() : ์ž‘์—…์Šค๋ ˆ๋“œ๋Š” ๋งค๊ฐœ๊ฐ’์œผ๋กœ ๋ฐ›์€ Runnable์˜ run() ๋ฉ”์†Œ๋“œ๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
Runnable task = new Task();
Thread thread = new Thread(task);

/* Ruunable ์ต๋ช… ๊ฐ์ฒด */
Thread thread = new Thread(new Runnable() {
    @Override
    public void run() {
        // ์Šค๋ ˆ๋“œ๊ฐ€ ์‹คํ–‰ํ•  ์ฝ”๋“œ
    }
});

/* Java8 ๋žŒ๋‹ค์‹ */
Thread thread = new Thread(() -> {
   // ์Šค๋ ˆ๋“œ๊ฐ€ ์‹คํ–‰ํ•  ์ฝ”๋“œ
});

// ์ž‘์—… ์Šค๋ ˆ๋“œ ์‹คํ–‰
thread.start();

extends thread

  • Thread ํด๋ž˜์Šค๋ฅผ ์ƒ์†ํ•œ ํ›„ run ๋ฉ”์†Œ๋“œ๋ฅผ ์žฌ์ •์˜(overriding)ํ•ด์„œ ์Šค๋ ˆ๋“œ๊ฐ€ ์‹คํ–‰ํ•  ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑ
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
public class WorkerThread extends Thread {
    @Override
    public void run() {
        // ์Šค๋ ˆ๋“œ๊ฐ€ ์‹คํ–‰ํ•  ์ฝ”๋“œ
    }
}
Thread thread = new WorkerThread();

/* ์ต๋ช…์˜ ์ž์‹ ๊ฐ์ฒด๋กœ ์ƒ์„ฑ */
Thread thread = new Thread() {
    @Override
    public void run() {
        // ์Šค๋ ˆ๋“œ๊ฐ€ ์‹คํ–‰ํ•  ์ฝ”๋“œ
    }
};

implements Runnable vs extends Thread

  • ์ž๋ฐ”์—์„œ๋Š” ๋‹ค์ค‘ ์ƒ์†์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— extends Thread์˜ ๊ฒฝ์šฐ ๋‹ค๋ฅธ ํด๋ž˜์Šค์˜ ์ƒ์†์„ ๋ฐ›์„ ์ˆ˜ ์—†๋‹ค.
  • ์ธํ„ฐํŽ˜์ด์Šค์˜ ๊ฒฝ์šฐ ๋‹ค์ค‘ ์ƒ์†์ด ๊ฐ€๋Šฅํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋‹ค๋ฅธ ํด๋ž˜์Šค๋ฅผ ์ƒ์† ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค.
  • ๊ทธ๋Ÿฌ๋ฏ€๋กœ implements Runnable์„ ํ†ตํ•ด ์žฌ ์ •์˜ํ•˜์—ฌ ํ™•์žฅํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๋‹ค.

์Šค๋ ˆ๋“œ์˜ ์ด๋ฆ„

  • ์Šค๋ ˆ๋“œ๋Š” ์ž์‹ ์˜ ์ด๋ฆ„์„ setName()๋กœ ๋ณ€๊ฒฝํ•œ๋‹ค.
  • ์Šค๋ ˆ๋“œ ๊ฐ์ฒด์˜ ์ฐธ์กฐ๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ Thread.currentThread()๋กœ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋Š” ํ˜„์žฌ ์Šค๋ ˆ๋“œ์˜ ์ฐธ์กฐ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค.
1
Thread thread = Thread.currentThread();

์Šค๋ ˆ๋“œ์˜ ์Šค์ผ€์ค„๋ง

  • ๋™์‹œ์„ฑ(Concurrency) : ํ•˜๋‚˜์˜ ์ฝ”์–ด์—์„œ ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋“œ๊ฐ€ ๋ฒˆ๊ฐˆ์•„๊ฐ€๋ฉฐ ์‹คํ–‰ํ•˜๋Š” ์„ฑ์งˆ
  • ๋ณ‘๋ ฌ์„ฑ(Parallelism) : ๋ฉ€ํ‹ฐ ์ฝ”์–ด์—์„œ ๊ฐœ๋ณ„ ์Šค๋ ˆ๋“œ๋ฅผ ๋™์‹œ์— ์‹คํ–‰ํ•˜๋Š” ์„ฑ์งˆ
  • ์Šค๋ ˆ๋“œ์˜ ๊ฐœ์ˆ˜๊ฐ€ ์ฝ”์–ด์˜ ์ˆ˜๋ณด๋‹ค ๋งŽ์„ ๊ฒฝ์šฐ, ์Šค๋ ˆ๋“œ๋ฅผ ์–ด๋–ค ์ˆœ์„œ์— ์˜ํ•ด ๋™์‹œ์„ฑ์œผ๋กœ ์‹คํ–‰ํ•  ๊ฒƒ ์ธ๊ฐ€๋ฅผ ๊ฒฐ์ •ํ•ด์•ผ ํ•œ๋‹ค. ์ด๊ฒƒ์„ ์Šค๋ ˆ๋“œ ์Šค์ผ€์ค„๋ง ์ด๋ผ๊ณ  ํ•œ๋‹ค.

์ž๋ฐ”์˜ ์Šค๋ ˆ๋“œ ์Šค์ผ€์ค„๋ง ๋ฐฉ์‹

  1. ์šฐ์„ ์ˆœ์œ„(Priority)๋ฐฉ์‹
    • ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋†’์€ ์Šค๋ ˆ๋“œ๊ฐ€ ์‹คํ–‰ ๊ธฐํšŒ๋ฅผ ๋” ๋งŽ์ด ๊ฐ–๋Š”๋‹ค.
    • ์Šค๋ ˆ๋“œ ๊ฐ์ฒด์— ์šฐ์„ ์ˆœ์œ„ ๋ฒˆํ˜ธ๋ฅผ ๋ถ€์—ฌํ•  ์ˆ˜ ์žˆ์–ด ๊ฐœ๋ฐœ์ž๊ฐ€ ์ฝ”๋“œ๋ฅผ ์ œ์–ดํ•  ์ˆ˜ ์žˆ๋‹ค.
    • ์šฐ์„ ์ˆœ์œ„๋Š” ๋™์‹œ์„ฑ์—์„œ๋งŒ ์˜๋ฏธ๊ฐ€ ์žˆ๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค.
  2. ์ˆœํ™˜ํ• ๋‹น(Round-Robin)๋ฐฉ์‹
    • ์‹œ๊ฐ„ ํ• ๋‹น๋Ÿ‰ Time Slice์„ ์ •ํ•ด์„œ ํ•˜๋‚˜์˜ ์Šค๋ ˆ๋“œ๋ฅผ ์ •ํ•ด์ง„ ์‹œ๊ฐ„๋งŒํผ ์‹คํ–‰ํ•œ๋‹ค.

์Šค๋ ˆ๋“œ ์šฐ์„ ์ˆœ์œ„

  • ์šฐ์„ ์ˆœ์œ„๋Š” 1์—์„œ๋ถ€ํ„ฐ 10๊นŒ์ง€ ๋ถ€์—ฌ. 1์ด ๊ฐ€์žฅ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋‚ฎ๊ณ  10์ด ๊ฐ€์žฅ ๋†’์Œ.
  • Thread ํด๋ž˜์Šค ์ƒ์ˆ˜๋กœ๋„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.
  • ๋งŒ์•ฝ ์ฟผ๋“œ ์ฝ”์–ด์ผ ๊ฒฝ์šฐ 4๊ฐœ์˜ ์Šค๋ ˆ๋“œ๊ฐ€ ๋ณ‘๋ ฌ์„ฑ์œผ๋กœ ์‹คํ–‰ ๋  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— 4๊ฐœ ์ดํ•˜์˜ ์Šค๋ ˆ๋“œ๋ฅผ ์‹คํ–‰ํ•  ๊ฒฝ์šฐ ์šฐ์„ ์ˆœ์œ„ ๋ฐฉ์‹์ด ํฌ๊ฒŒ ์˜ํ–ฅ์„ ๋ฏธ์น˜์ง€ ๋ชปํ•จ.
1
2
3
thread.setPriority(Thread.MAX_PRIORITY); // 10
thread.setPriority(Thread.NORM_PRIORITY); // 5
thread.setPriority(Thread.MIN_PRIORITY); // 1

๋™๊ธฐํ™” ๋ฉ”์†Œ๋“œ์™€ ๋™๊ธฐํ™” ๋ธ”๋ก

๊ณต์œ  ๊ฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ์ฃผ์˜ํ•  ์ 

  • ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋“œ์—์„œ๋Š” ์Šค๋ ˆ๋“œ๋“ค์ด ๊ฐ์ฒด๋ฅผ ๊ณต์œ ํ•ด์„œ ์ž‘์—…ํ•ด์•ผ ํ•˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ์žˆ์Œ.
  • ์Šค๋ ˆ๋“œ A๋ฅผ ์‚ฌ์šฉํ•˜๋˜ ๊ฐ์ฒด๊ฐ€ ์Šค๋ ˆ๋“œ B์— ์˜ํ•ด ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์˜๋„ํ–ˆ๋˜ ๊ฒƒ๊ณผ ๋‹ค๋ฅธ ๊ฒฐ๊ณผ๋ฅผ ์‚ฐ์ถœ ๋  ์ˆ˜ ์žˆ๋‹ค.

synchronized

  • ์ž„๊ณ„ ์˜์—ญ(critical section) : ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋“œ ํ”„๋กœ๊ทธ๋žจ์—์„œ ๋‹จ ํ•˜๋‚˜์˜ ์Šค๋ ˆ๋“œ๋งŒ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ์ฝ”๋“œ ์˜์—ญ
  • ์ž๋ฐ”๋Š” ์ž„๊ณ„์˜์—ญ์„ ์ง€์ •ํ•˜๊ธฐ ์œ„ํ•ด ๋™๊ธฐํ™”(synchronize) ๋ฉ”์†Œ๋“œ์™€ ๋ธ”๋ก์„ ์ œ๊ณต.
  • ์Šค๋ ˆ๋“œ๊ฐ€ ๊ฐ์ฒด ๋‚ด๋ถ€์˜ ๋™๊ธฐํ™” ๋ฉ”์†Œ๋“œ ๋˜๋Š” ๋ธ”๋ก์— ๋“ค์–ด๊ฐ€๋ฉด ์ฆ‰์‹œ ๊ฐ์ฒด์— ์ž ๊ธˆ์„ ๊ฑธ์–ด ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๊ฐ€ ์ž„๊ณ„ ์˜์—ญ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜์ง€ ๋ชปํ•˜๋„๋ก ํ•œ๋‹ค.
  • synchronized ํ‚ค์›Œ๋“œ๋Š” ์ธ์Šคํ„ด์Šค์™€ ์ •์  ๋ฉ”์†Œ๋“œ ์–ด๋””๋“  ๋ถ™์ผ ์ˆ˜ ์žˆ๋‹ค.
1
2
3
public synchronized void method() {
    // ์ž„๊ณ„ ์˜์—ญ;
}
1
2
3
4
5
6
7
8
9
public void method() {
    // ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๊ฐ€ ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ์˜์—ญ
    ...
    synchronized(๊ณต์œ ๊ฐ์ฒด) { /*๋™๊ธฐํ™” ๋ธ”๋ก*/
        // ์ž„๊ณ„ ์˜์—ญ
    }
    // ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๊ฐ€ ์‹คํ–‰ ๊ฐ€๋Šฅํ•œ ์˜์—ญ
    ...
}

์Šค๋ ˆ๋“œ ์ƒํƒœ

  • ์Šค๋ ˆ๋“œ ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜๊ณ  start() ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ์‹คํ–‰ ๋Œ€๊ธฐ ์ƒํƒœ๊ฐ€ ๋œ๋‹ค.
  • ์‹คํ–‰ ๋Œ€๊ธฐ๋ž€ ์•„์ง ์Šค์ผ€์ค„๋ง์ด ๋˜์ง€ ์•Š์•„ ์‹คํ–‰์„ ๊ธฐ๋‹ค๋ฆฌ๊ณ  ์žˆ๋Š” ์ƒํƒœ๋ฅผ ์˜๋ฏธํ•œ๋‹ค.
  • ์‹คํ–‰ ๋Œ€๊ธฐ ์ƒํƒœ์— ์žˆ๋Š” ์Šค๋ ˆ๋“œ ์ค‘ ์Šค๋ ˆ๋“œ ์Šค์ผ€์ค„๋ง์— ์˜ํ•ด CPU๋ฅผ ์ ์œ ํ•˜๊ณ  run() ๋ฉ”์†Œ๋“œ๋ฅผ ์‹คํ–‰ํ•œ๋‹ค.
  • ์ผ์‹œ ์ •์ง€ ์ƒํƒœ : WAITING, TIMED_WAITING, BLOCKED

Thread.State ์—ด๊ฑฐ ์ƒ์ˆ˜

์ƒํƒœ ์—ด๊ฑฐ ์ƒ์ˆ˜ ์„ค๋ช…
๊ฐ์ฒด ์ƒ์„ฑ NEW ์Šค๋ ˆ๋“œ ๊ฐ์ฒด ์ƒ์„ฑ. ์•„์ง start() ๋ฉ”์†Œ๋“œ ํ˜ธ์ถœ ์ „.
์‹คํ–‰ ๋Œ€๊ธฐ RUNNABLE ์‹คํ–‰ ์ƒํƒœ๋กœ ์–ธ์ œ๋“ ์ง€ ๊ฐˆ ์ˆ˜ ์žˆ๋Š” ์ƒํƒœ.
์ผ์‹œ ์ •์ง€ WAITING ๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ๊ฐ€ ํ†ต์ง€(Notify)ํ•  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ๋Š” ์ƒํƒœ
์ผ์‹œ ์ •์ง€ TIMED_WAITING ์ฃผ์–ด์ง„ ์‹œ๊ฐ„ ๋™์•ˆ ๊ธฐ๋‹ค๋ฆฌ๋Š” ์ƒํƒœ
์ผ์‹œ ์ •์ง€ BLOCKED ์‚ฌ์šฉํ•˜๊ณ ์ž ํ•˜๋Š” ๊ฐ์ฒด์˜ ๋ฝ์ด ํ’€๋ฆด ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ๋Š” ์ƒํƒœ
์ข…๋ฃŒ TERMINATED ์‹คํ–‰์„ ๋งˆ์นœ ์ƒํƒœ

์Šค๋ ˆ๋“œ ์ƒํƒœ ์ œ์–ด

  • ์Šค๋ ˆ๋“œ ์ƒํƒœ ์ œ์–ด : ์‹คํ–‰ ์ค‘์ธ ์Šค๋ ˆ๋“œ์˜ ์ƒํƒœ๋ฅผ ๋ณ€๊ฒฝํ•˜๋Š” ๊ฒƒ
  • ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ๋Š” ์ •๊ตํ•œ ์Šค๋ ˆ๋“œ ์ƒํƒœ ์ œ์–ด๊ฐ€ ํ•„์š”ํ•˜๋ฉฐ, ์Šค๋ ˆ๋“œ์˜ ์ƒํƒœ ๋ณ€ํ™”๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋ฉ”์†Œ๋“œ๋ฅผ ํŒŒ์•…ํ•ด์•ผ ํ•œ๋‹ค.