Posts Java Thread
Post
Cancel

Java Thread

Java Thread


๐Ÿ’ฟ Thread LifeCycle

image

  • New: Thread.start() ํ•˜๋ฉด ์‹คํ–‰๋จ
  • Runnable: startํ•˜๋ฉด runnable๋กœ ๋ฐ”๋€œ
    • Control์ด Thread Scheduler๋กœ ๊ฐ€์„œ ์‹คํ–‰์„ ๊ธฐ๋‹ค๋ฆผ
  • Running: Scheduler๊ฐ€ ์‹คํ–‰์„ ์‹œํ‚จ ์ƒํƒœ
  • Blocked
    • Waiting for I/O resources
    • Waiting for a monitor lock
  • Waiting: ๋‹ค๋ฅธ Thread๊ฐ€ ํŠน์ • action์„ performํ•˜๊ธธ ๊ธฐ๋‹ค๋ฆฌ๋Š” ์ƒํƒœ
    • Object.wait with no timeout
    • Thread.join with no timeout
    • ์˜ˆ๋ฅผ ๋“ค์–ด Object.wait()๋ฅผ ํŠน์ • object์— ํ˜ธ์ถœํ•œ ํ›„ ๋‹ค๋ฅธ ์“ฐ๋ ˆ๋“œ๊ฐ€ Object.notify or Object.notifyAll()๋ฅผ ๊ทธ Object์— ํ˜ธ์ถœํ•˜๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋Š” ์ƒํƒœ
    • waiting์ด ๋๋‚˜๋ฉด Runnable๋กœ ๋Œ์•„๊ฐ
  • Timed_Waiting: ๋ฐ‘์˜ ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœ ํ•ด์„œ waiting ์ƒํƒœ
    • Thread.sleep
    • Object.wait with timeout
    • Thread.join with timeout
  • Terminated: run()์ด ๋๋‚˜๋ฉด ์ž์›์„ ๋ฐ˜๋‚ฉํ•˜๊ณ  ์ข…๋ฃŒ

๐Ÿ’ฟ Thread ์ƒ์„ฑ์ž

ํ•จ์ˆ˜์„ค๋ช…
Thread()์Šค๋ ˆ๋“œ ์ด๋ฆ„
Thread(Runnable r)์ธํ„ฐํŽ˜์ด์Šค ๊ฐ์ฒด
Thread(Runnable r, String s)์ธํ„ฐํŽ˜์ด์Šค ๊ฐ์ฒด์™€ ์Šค๋ ˆ๋“œ ์ด๋ฆ„

๐Ÿ’ฟ Thread Method

ํ•จ์ˆ˜์„ค๋ช…
static void sleep(long msec)
throws Interrupted Exception
msec์— ์ง€์ •๋œ ๋ฐ€๋ฆฌ์ดˆ ๋™์•ˆ ๋Œ€๊ธฐ
String getName()์Šค๋ ˆ๋“œ์˜ ์ด๋ฆ„์„ s๋กœ ์„ค์ •
void setName(String s)์Šค๋ ˆ๋“œ์˜ ์ด๋ฆ„์„ s๋กœ ์„ค์ •
void start()์Šค๋ ˆ๋“œ๋ฅผ ์‹œ์ž‘ run() ๋ฉ”์†Œ๋“œ ํ˜ธ์ถœ
int getPriority()์Šค๋ ˆ๋“œ์˜ ์šฐ์„  ์ˆœ์œ„๋ฅผ ๋ฐ˜ํ™˜
void setpriority(int p)์Šค๋ ˆ๋“œ์˜ ์šฐ์„ ์ˆœ์œ„๋ฅผ p๊ฐ’์œผ๋กœ
boolean isAlive()์Šค๋ ˆ๋“œ๊ฐ€ ์‹œ์ž‘๋˜์—ˆ๊ณ  ์•„์ง ๋๋‚˜์ง€ ์•Š์•˜์œผ๋ฉด
true ๋๋‚ฌ์œผ๋ฉด false ๋ฐ˜ํ™˜
void join()
throws InterruptedException
์Šค๋ ˆ๋“œ๊ฐ€ ๋๋‚  ๋•Œ ๊นŒ์ง€ ๋Œ€๊ธฐ
void run()์Šค๋ ˆ๋“œ๊ฐ€ ์‹คํ–‰ํ•  ๋ถ€๋ถ„ ๊ธฐ์ˆ 
(์˜ค๋ฒ„๋ผ์ด๋”ฉ ์‚ฌ์šฉ)
void suspend()์Šค๋ ˆ๋“œ๊ฐ€ ์ผ์‹œ์ •์ง€ resume()์—
์˜ํ•ด ๋‹ค์‹œ์‹œ์ž‘ ํ•  ์ˆ˜ ์žˆ๋‹ค.
void resume()์ผ์‹œ ์ •์ง€๋œ ์Šค๋ ˆ๋“œ๋ฅผ ๋‹ค์‹œ ์‹œ์ž‘.
void yield()๋‹ค๋ฅธ ์Šค๋ ˆ๋“œ์—๊ฒŒ ์‹คํ–‰ ์ƒํƒœ๋ฅผ ์–‘๋ณดํ•˜๊ณ 
์ž์‹ ์€ ์ค€๋น„ ์ƒํƒœ๋กœ

๐Ÿ’ฟ Thread ์ƒ์„ฑ

extend Thread

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class Test extends Thread {
    int seq;
    public Test(int seq) {
        this.seq = seq;
    }
    public void run() {
        System.out.println(this.seq+" thread start.");
        try {
            Thread.sleep(1000);
        }catch(Exception e) {

        }
        System.out.println(this.seq+" thread end.");
    }

    public static void main(String[] args) {
        for(int i=0; i<10; i++) {
            Thread t = new Test(i);
            t.start();
        }
        System.out.println("main end.");
    }
}

output

1
2
3
4
5
6
7
8
9
0 thread start.
4 thread start.
6 thread start.
2 thread start.
main end.
3 thread start.
...
1 thread end.
5 thread end.
  • ํŠน์ง•
    • test.start() ์‹คํ–‰ ์‹œ test๊ฐ์ฒด์˜ run ๋ฉ”์†Œ๋“œ๊ฐ€ ์ˆ˜ํ–‰
    • ์“ฐ๋ ˆ๋“œ๊ฐ€ ์ข…๋ฃŒ๋˜๊ธฐ ์ „์— main ๋ฉ”์†Œ๋“œ๊ฐ€ ์ข…๋ฃŒ

๐Ÿ’ฟ Join

์“ฐ๋ ˆ๋“œ๊ฐ€ ์ข…๋ฃŒ๋  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ๊ฒŒ ํ•˜๋Š” ๋ฉ”์„œ๋“œ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public static void main(String[] args) {
    ArrayList<Thread> threads = new ArrayList<Thread>();
    for(int i=0; i<10; i++) {
        Thread t = new Test(i);
        t.start();
        threads.add(t);
    }

    for(int i=0; i<threads.size(); i++) {
        Thread t = threads.get(i);
        try {
            t.join();
        }catch(Exception e) {
        }
    }
    System.out.println("main end.");
}

output

1
2
3
4
5
6
0 thread start.
5 thread start.
2 thread start.
6 thread start.
...
main end.
  • ํŠน์ง•
    • ๋ชจ๋“  ์“ฐ๋ ˆ๋“œ๊ฐ€ ์ข…๋ฃŒ๋œ ํ›„์— main ๋ฉ”์†Œ๋“œ๋ฅผ ์ข…๋ฃŒ

๐Ÿ’ฟ Runnable

ํ”ํžˆ ์‚ฌ์šฉ๋˜๋Š” ๋ฐฉ๋ฒ•

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class Test implements Runnable {
    int seq;
    public Test(int seq) {
        this.seq = seq;
    }
    public void run() {
        System.out.println(this.seq+" thread start.");
        try {
            Thread.sleep(1000);
        }catch(Exception e) {
        }
        System.out.println(this.seq+" thread end.");
    }

    public static void main(String[] args) {
        ArrayList<Thread> threads = new ArrayList<Thread>();
        for(int i=0; i<10; i++) {
            Thread t = new Thread(new Test(i));
            t.start();
            threads.add(t);
        }

        for(int i=0; i<threads.size(); i++) {
            Thread t = threads.get(i);
            try {
                t.join();
            }catch(Exception e) {
            }
        }
        System.out.println("main end.");
    }
}
  • ํŠน์ง•
    • Thread t = new Thread(new Test(i));

๐Ÿ’ฟ Thread ์šฐ์„ ์ˆœ์œ„

์šฐ์„ ์ˆœ์œ„๋ผ๋Š” ์†์„ฑ(๋ฉค๋ฒ„๋ณ€์ˆ˜)์˜ ๊ฐ’์— ๋”ฐ๋ผ ์“ฐ๋ ˆ๋“œ๊ฐ€ ์–ป๋Š” ์‹คํ–‰์‹œ๊ฐ„์ด ๋‹ฌ๋ผ์ง

  • ์“ฐ๋ ˆ๋“œ๊ฐ€ ์ˆ˜ํ–‰ํ•˜๋Š” ์ž‘์—…์˜ ์ค‘์š”๋„์— ๋”ฐ๋ผ ์“ฐ๋ ˆ๋“œ์˜ ์šฐ์„ ์ˆœ์œ„๋ฅผ ์„œ๋กœ ๋‹ค๋ฅด๊ฒŒ ์ง€์ •ํ•˜์—ฌ ํŠน์ • ์“ฐ๋ ˆ๋“œ๊ฐ€ ๋” ๋งŽ์€ ์ž‘์—…์‹œ๊ฐ„์„ ๊ฐ–๋„๋ก ํ•  ์ˆ˜ ์žˆ๋‹ค
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class ThreadPriority {

	public static void main(String args[]) {

		A th1 = new A();
		B th2 = new B();

		th1.setPriority(4); // defalut ์šฐ์„ ์ˆœ์œ„ 5
		th2.setPriority(7);

		System.out.println("Priority of th1(-): " + th1.getPriority());
		System.out.println("Priority of th2(|): " + th2.getPriority());

		th1.start();
		th2.start();

	}

}

class A extends Thread {

	public void run() {
		for(int i=0; i < 300; i++) {
			System.out.print("-");
			for(int x=0; x < 10000000; x++);
		}
	}
}

class B extends Thread {

	public void run() {
		for(int i=0; i < 300; i++) {
			System.out.print("|");
			for(int x=0; x < 10000000; x++);
		}
	}	
}

์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋†’์€ th2์˜ ์‹คํ–‰์‹œ๊ฐ„์ด th1์— ๋น„ํ•ด ์ƒ๋‹นํžˆ ๋Š˜์–ด๋‚œ๋‹ค.


๐Ÿ’ฟ Main ์“ฐ๋ ˆ๋“œ

๋ฉ”์ธ์ด ์ˆ˜ํ–‰ํ•˜๋Š” ์Šค๋ ˆ๋“œ public static void main(String[] args)

image

  • The main thread is created automatically when our program is started

Main Thread Controll

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
public class Test extends Thread {
	public static void main(String[] args) {

	// getting reference to Main thread
	Thread t = Thread.currentThread();
  
	// getting name of Main thread
	System.out.println("Current thread: " + t.getName());
  
	// changing the name of Main thread
	t.setName("Geeks");
	System.out.println("After name change: " + t.getName());
  
	// getting priority of Main thread
	System.out.println("Main thread priority: "+ t.getPriority());
  
	// setting priority of Main thread to MAX(10)
	t.setPriority(MAX_PRIORITY);
  
	System.out.println("Main thread new priority: "+ t.getPriority());
  
	for (int i = 0; i < 2; i++) {
		System.out.println("Main thread");
	}
  
	// Main thread creating a child thread
	ChildThread ct = new ChildThread();

	// getting priority of child thread
	// which will be inherited from Main thread
	// as it is created by Main thread
	System.out.println("Child thread priority: "+ ct.getPriority());

	// setting priority of Main thread to MIN(1)
	ct.setPriority(MIN_PRIORITY);

	System.out.println("Child thread new priority: "+ ct.getPriority());

	// starting child thread
	ct.start();
	}
}

// Child Thread class
class ChildThread extends Thread {
	@Override
	public void run() {
		for (int i = 0; i < 2; i++){
			System.out.println("Child thread");
		}
	}
}

output

1
2
3
4
5
6
7
8
9
10
Current thread: main
After name change: Geeks
Main thread priority: 5
Main thread new priority: 10
Main thread
Main thread
Child thread priority: 10
Child thread new priority: 1
Child thread
Child thread

๋™๊ธฐํ™”

Synchronized๋ฅผ ์ด์šฉํ•œ ๋™๊ธฐํ™”

๊ฐ์ฒด์— lock์„ ๊ฑธ๊ณ ์ž ํ•  ๋•Œ

1
2
3
4
5
synchronized(๊ฐ์ฒด์˜ ์ฐธ์กฐ๋ณ€์ˆ˜){

//.....

}

method์— lock์„ ๊ฑธ๊ณ ์ž ํ•  ๋•Œ

1
2
3
4
5
public synchronized void calcSum(){

//.....

}
  • ํ•จ์ˆ˜์— synchronized๋ฅผ ๊ฑธ๋ฉด ๊ทธ ํ•จ์ˆ˜๊ฐ€ ํฌํ•จ๋œ ํ•ด๋‹น ๊ฐ์ฒด(this)์— lock์„ ๊ฑฐ๋Š”๊ฒƒ

Example

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
class ThreadEx24 {
	public static void main(String args[]) {

		Runnable r = new A();
		Thread t1 = new Thread(r);
		Thread t2 = new Thread(r);

		t1.start();
		t2.start();
	}
}

class Account {
	int balance = 1000;
	public synchronized void withdraw(int money){ //synchronized ํ‚ค์›Œ๋“œ๋ฅผ ๋ถ™์ด๊ธฐ๋งŒ ํ•˜๋ฉด ๊ฐ„๋‹จํžˆ ๋™๊ธฐํ™”๊ฐ€ ๋œ๋‹ค.

		if(balance >= money) {
			try { Thread.sleep(1000);} catch(Exception e) {}
			balance -= money;
		}
	} // withdraw
}

class A implements Runnable {

	Account acc = new Account();
	public void run() {

		while(acc.balance > 0) {
			// 100, 200, 300์ค‘์˜ ํ•œ ๊ฐ’์„ ์ž„์œผ๋กœ ์„ ํƒํ•ด์„œ ์ถœ๊ธˆ(withdraw)

			int money = (int)(Math.random() * 3 + 1) * 100;
			acc.withdraw(money);
			System.out.println("balance:"+acc.balance);
		}
	} // run()
}
  • Synchronized๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์œผ๋ฉด ์˜ˆ์ƒ์น˜ ๋ชปํ•œ ๊ฒฐ๊ณผ๊ฐ€ ๋‚˜์˜จ๋‹ค

DeadLock

imgae

์ž„๊ณ„์˜์—ญ: ๋‘˜ ์ด์ƒ์˜ ์“ฐ๋ ˆ๋“œ๊ฐ€ ๋™์‹œ์— ์‹คํ–‰๋  ๊ฒฝ์šฐ ์ƒ๊ธธ ์ˆ˜ ์žˆ๋Š” ๋™์‹œ ์ ‘๊ทผ ๋ฌธ์ œ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋Š” ์ฝ”๋“œ ๋ธ”๋ก(Critical Section)

  • Thread1์ด A์˜ ์ž„๊ณ„์˜์—ญ(test1)์— ์ง„์ž… ํ›„ ์ž„๊ณ„์˜์—ญ์—์„œ ํƒˆ์ถœ ํ•˜์ง€ ์•Š์€ ์ฑ„ B์˜ ์ž„๊ณ„์˜์—ญ(test2)์— ์ง„์ž…
    • B์— ์ง€์ž…ํ•œ ์ƒํ™ฉ์—์„  A๋Š” Lock์„ ํš๋“ํ•ด Blocked ์ƒํƒœ
    • Thread2๊ฐ€ ์ž„๊ณ„์˜์—ญ(test1) ์ง„์ž… ํ•œ ์ƒํƒœ์ด๋ฏ€๋กœ BLOCKED ๋จ
      • Thread2๊ฐ€ test1์„ ํ†ตํ•ด ObectA์˜ test2์— ์ง„์ž…ํ•˜๋ ค ํ•˜์ง€๋งŒ Lock์ด ํ’€๋ฆฌ์ง€ ์•Š์•˜์œผ๋ฉฐ BLOCKED

๊ฒฐ๊ณผ์ ์œผ๋กœ 2๊ฐœ์˜ Thread๊ฐ€ ์„œ๋กœ LOCK์„ ํ•ด์ œํ•˜๊ธฐ๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋ฏ€๋กœ ์˜์›ํžˆ BLOCKED ๋จ

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
public class DeadLockTest { 

    @Test 
    public void runDeadLock() { 

        Shared s1 = new Shared(); 
        Shared s2 = new Shared(); 

        ExecutorService es = Executors.newFixedThreadPool(3); 

        Future<?> future1 = es.submit(new Task(s1, s2)); 
        Future<?> future2 = es.submit(new Task(s2, s1)); 

        es.shutdown(); 

        try { 
            int awaitCnt = 0; 

            while (!es.awaitTermination(10, TimeUnit.SECONDS)) { 

                System.out.println("Not a terminate threads. "); 

                reportDeadLockThread(); 

                awaitCnt++;

                if ( awaitCnt > 3 && !future1.isCancelled() && !future2.   isCancelled() ) { 
                    // (4)
                    future1.cancel(true); 
                    future2.cancel(true); 
                } 
            } 
        } catch (InterruptedException e) { 
            Thread.currentThread().interrupt(); 
        } 
    } 

    // (5) 
    private void reportDeadLockThread() { 

        ThreadMXBean bean = ManagementFactory.getThreadMXBean(); // Returns null if no threads are deadlocked. 

        long[] threadIds = bean.findDeadlockedThreads(); 

        if (threadIds != null) { 
            ThreadInfo[] infos = bean.getThreadInfo(threadIds); 
            for (ThreadInfo info : infos) { 
                String s = info.getThreadName(); 
                System.out.println(String.format("DeadLocked Thread Name >>>> %s", s)); 
            } 
        } 
    } 
    
    static class Shared { 
        // (1) 
        synchronized void test1(Shared s2) { 
            System.out.println("test1-begin"); 
            
            ThreadUtil.sleep(1000); 

            // (2) 
            s2.test2(this); 

            System.out.println("test1-end"); 
        } 

        // (3) 
        synchronized void test2(Shared s1) { 
            System.out.println("test2-begin"); 

            ThreadUtil.sleep(1000); 

            // taking object lock of s1 enters 
            // into test1 method 
            s1.test1(this); 

            System.out.println("test2-end"); 
        } 
    } 
    
    static class Task implements Runnable { 
        private Shared s1; 
        private Shared s2; 
        // constructor to initialize fields 
        Task(Shared s1, Shared s2) { 
            this.s1 = s1; 
            this.s2 = s2; 
        } 
        // run method to start a thread 
        @Override public void run() { 
            // taking object lock of s1 enters 
            // into test1 method 
            s1.test1(s2); 
        } 
    } 
}
  1. runDeadLock ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด์„œ thread 1, thread 2๊ฐ€ ๊ฑฐ์˜ ๋™์‹œ์— ์‹œ์ž‘
    • ๊ฐ thread๋Š” test1() ํ•จ์ˆ˜์˜ ์‹คํ–‰์„ ์‹œ์ž‘ํ•œ๋‹ค.
    • this์˜ ๋™๊ธฐํ™” ๋ธ”๋Ÿญ์ด ์‹œ์ž‘๋˜๋ฉด์„œ ์ž์—ฐ์Šค๋ ˆ Lock๊ฐ์ฒด๋ฅผ ๊ณต์œ ํ•˜๋Š” test2()๋„ Lock์ด ๊ฑธ๋ฆฐ๋‹ค.
  2. ๋‹ค๋ฅธ๊ฐ์ฒด ์ฆ‰ s2๊ฐ์ฒด์˜ test2() ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•œ๋‹ค.
    • ๋‹ค๋ฅธ thread๋„ ๋™์‹œ์— ์ถœ๋ฐœ ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด ํ•จ์ˆ˜๋Š” ์ด๋ฏธ Lock์ด ๊ฑธ๋ ค์„œ ์ด ํ˜ธ์ถœ thread๋Š” ์ด ์ง€์ ์—์„œ BLOCKED ๋œ๋‹ค.
    • test2() ํ•จ์ˆ˜๊ฐ€ synchronized๊ฐ€ ์„ ์–ธ๋˜์ง€ ์•Š์•˜๋‹ค๋ฉด Thread2์—์„œ test1์„ ํ†ตํ•ด test2๋ฅผ ์‹คํ–‰์‚ฌ๊ณ  Lock์ด ํ’€๋ ค s1 ๊ฐ์ฒด๋„ ์ •์ƒ ์‹คํ–‰ ๋˜์—ˆ์„ ๊ฒƒ์ด๋‹ค.
  3. ํ•ด๋‹น thread๋ฅผ cancel์„ ํ–ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์•„๋ฌด ํšจ๊ณผ๊ฐ€ ์—†๋‹ค.
    • ์•”๋ฌต์ ์ธ Lock์ด BLOCKED ๋˜๋ฉด ์ค‘๋‹จ์‹œํ‚ฌ ๋ฐฉ๋ฒ•์ด ์—†๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.
This post is licensed under CC BY 4.0 by the author.

Spring-Web

Thread Process