Language/Java

[JAVA 35] 자바 쓰레드 ( Thread )

reifier.tistory.com 으로 이전하였습니다. 2018. 2. 20. 21:06
반응형


■ Thread ( 쓰레드 )

1. 프로세스를 구성하는 ' 제어의 흐름 ' 이다.

2. Process 와 Thread

- Process : 프로그램의 실행 단위

- Thread  : Process 를 구성하는 작업 단위


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
class ThreadS1 extends Thread{        // Thread Study 1
    
    ThreadS1(){
        start();
        while(true){
            try{
                Thread.sleep(1000); // 1초 잠들어 있다가 실행을 반복 ( msec )
            }catch(InterruptedException ie){
                System.out.println("생성자() 예외");
            }
            System.out.println("행동1");
        }
    }
 
    public void run(){    // run(); 메소드는 4번째 줄에 있는 start(); 가 호출한다.
        while(true){
            try{
                Thread.sleep(500); // 0.5초 잠들어 있다가 실행을 반복 ( msec )
            }catch(InterruptedException ie){
                System.out.println("쓰레드 메소드() 예외");
            }
            System.out.println("행동2");
        }
    }
 
    public static void main(String[] args){
        new ThreadS1();
    }
}
cs




3.. 특징

쓰레드는 프로세스 와 ' 공통 Resource ' 를 서로 공유하기 때문에 

' 경량 프로세스 ' 라고 불릴 정도로 가볍다.

4. 생성 방법

1) java.lang.Thread 를 상속받는 방법       ~ extends Thread

2) java.lang.Runnable 을 구현하는 방법    ~ implements 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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
class Thread1 extends Thread{
    public void run(){
        while(true){
            try{
                Thread.sleep(1000);
            }catch(InterruptedException ie){
                System.out.println("Thread1 예외");
            }
            System.out.println("행동 1");
        }
    }
}
 
class Thread2 implements Runnable{
    public void run(){
        while(true){
            try{
                Thread.sleep(1000);
            }catch(InterruptedException ie){
                System.out.println("Thread2 예외");
            }
            System.out.println("행동 2");
        }
    }
}
 
class User2{
 
    User2(){
        Thread th1 = new Thread1();
        th1.start();    // JVM → 제어 → run()
        
        Runnable r = new Thread2();
        Thread th2 = new Thread(r);
        th2.start();
 
        while(true){
            try{
                Thread.sleep(1000);
            }catch(InterruptedException ie){
                System.out.println("User2 생성자 예외");
            }
            System.out.println("행동 3");
        }
    }
 
    public static void main(String[] args){
        new User2();
    }
}
cs




5. 시작 메소드

쓰레드객체.start();

6.    ex1) 인터넷에서 음악을 들으면서 그 음악을 다운로드

6.    ex2) 게임을 플레이 하면서 대화를 함과 동시에 배경음악이 나온다.

6.    ex3) 문자 입력과 동시에 오타처리

6.    ex4) 메신저에서 파일을 다운로드 중에 채팅 가능

등등


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
class Action1 extends Thread{
    
    public void run(){
        action1();
    }
    
    private void action1(){
        while(true){
            try{
                Thread.sleep(1500);
            }catch(InterruptedException ie){}
            System.out.println("행동 1");
        }
    }
}
 
class Action2 extends Thread{
 
    public void run(){
        action2();
    }
 
    private void action2(){
        while(true){
            try{
                Thread.sleep(1000);
            }catch(InterruptedException ie){}
            System.out.println("행동 2");
        }
    }
}
 
class User3{
 
    User3(){
        new Action1().start();
        new Action2().start();
        action3();
    }
 
    void action3(){
        while(true){
            try{
                Thread.sleep(2000);
            }catch(InterruptedException ie){}
            System.out.println("행동 3");
        }
    }
 
    public static void main(String[] args){
        new User3();
    }
}
cs



7. Priority

1) Ready 상태의 쓰레드 중에서 , 우선적으로 CPU를 점유할 수 있는 쓰레드를 판별하기 위한 LEVEL 값

2) 범위

1 ~ 10

숫자가 클수록 우선순위가 높아진다.

3) 상수

MAX_PRIORITY

MIN_PRIORITY

NORM_PRIORITY


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
class YieldS1 extends Thread{    // yield study 1
    public void run(){
        for(int a=0 ; a < 1000 ; a++){
            System.out.println("a : " + a);
            yield();
        }
    }
}
 
class ThreadS4 extends Thread{
    Thread th1;
    Thread th2;
 
    ThreadS4(){
        int max = Thread.MAX_PRIORITY;
        int min = Thread.MIN_PRIORITY;
        int norm = Thread.NORM_PRIORITY;
 
        System.out.println("max : " + max);
        System.out.println("min : " + min);
        System.out.println("norm : " + norm);
    }
 
    public static void main(String[] args){
        new ThreadS4();
    }
}
cs



8. LifeCycle

1) 5가지의 상태로 구성되어 있다.

2) 상태이동은 메소드나 스케쥴러에 의해 가능하다.

3) ' 소멸상태 ' run()의 {}이 수행되면 자동으로 이동된다. 

( 단, 메인쓰레드는 main()의 {}가 수행되면 이동이 된다. )

cf1) wait() , notify() , notifyAll() 메소드는 항상 synchronized 블럭 내에서 사용되어야 한다.

cf2) wait() , sleep() 사용시에는 InterruptedException 예외를 처리해야 한다.




9. 주요메소드

1) sleep(시간) : 해당 시간동안만 waiting 상태에 존재한다.

2) yield()        .: running 상태의 쓰레드가 양보하게 한다.


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
class YieldS1 extends Thread{    // yield study 1
    public void run(){
        for(int a=0 ; a < 100 ; a++){
            System.out.println("a : " + a);
            yield();
        }
    }
}
 
class ThreadS4 extends Thread{
    Thread th1;
    Thread th2;
 
    ThreadS4(){
        th1 = new YieldS1();
        th1.setPriority(Thread.MIN_PRIORITY);
        th1.yield();
        th1.start();
 
        th2 = this;
        th2.setPriority(Thread.MAX_PRIORITY);
        th2.start();
    }
 
    void showP(){    // show priority
        int pt = this.getPriority();    // b 의 행동을 우선순위를 높게 준다.
        System.out.println("pt : " + pt);
    }
 
    public void run(){
        for(int b=0 ; b<100 ; b++){
            System.out.println("b : " + b);
            yield();
        }
    }
 
    public static void main(String[] args){
        ThreadS4 ts4 = new ThreadS4();
        ts4.showP();
    }
}
cs




3) join()        .: 자식 쓰레드에 적용하게 되면 부모 쓰레드는 자식이 죽을 때 까지 기다리게 된다.


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
class TS1 extends Thread{    // Thread Study 1
    
    public void run(){
        try{
            Thread.sleep(5000);    // 5초 뒤에 끝
        }catch(InterruptedException ie){}
        System.out.println("쓰레드 1 끝");
    }
}
 
class TS2 implements Runnable{    // Thread Study 2
    
    public void run(){
        Thread th = new TS1();
        th.start();
        try{
            Thread.sleep(3000);    // 3초 뒤에 끝
            th.join();
        }catch(InterruptedException ie){}
        System.out.println("쓰레드 2 끝");
    }
}
 
class TS3{
    Thread th;
 
    TS3(){
        th = new Thread(new TS2());
        th.start();
 
        try{
            th.join();
        }catch(InterruptedException ie){}
    }
 
    public static void main(String[] args){
        new TS3();
        System.out.println("메인 쓰레드 끝");
    }
}
cs


TS2 는 3초 뒤에 끝나고 TS1 은 5초뒤에 끝나기 때문에 

"쓰레드 2 끝"이 "쓰레드 1 끝"보다 2초 빠르게 출력이 되어야 한다.

하지만 join(); 으로 인해서 "쓰레드 1 끝"을 기다리고 함께 끝이 나게 된다.


10. 쓰레드 동기화

1)  하나 이상의 쓰레드가 어떤 연산에 동시에 접근했을 때

그 연산에 대한 값의 무결성을 보장하기 위해서 수행 영역에 대한 LOCK을 걸어 주는 것

ex1) 화장실의 문고리

ex2)    static int i = 0;

    i++;

# CPU 연산 단계 #                                A         B

(1) 현재의 i 값을 읽는 단계                    i==0    i==0 ( 무결성이 깨진다. )

(2) i 값을 증가시키는 단계                     i==0    i==0

(3) 증가된 i 값을 i 에 저장하는 단계         i==1    i==1


2) a. synchronized void m1(){ 연산 }

b. void m2(){

    {synchronized(this){

    연산

     }}

    }

synchronized 로 감싸진 영역을 동기화 블록이라고 한다.

동기화 블록 내에서는 오직 하나의 쓰레드만이 동시에 작업을 수행할 수 있다.


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
class ThreadS5 extends Thread{    // Thread Study 5
    
    static int a;
 
    ThreadS5(){
        start();
    }
 
    public void run(){
        m1();
        m2();
    }
 
    synchronized void m1(){
        a++;
        System.out.println("a : " + a);
    }
 
    void m2(){
        int b = 0;
        b--;
        {synchronized(this){
            a++;
        }}
        System.out.println("b : " + b);
    }
 
    public static void main(String[] args){
        new ThreadS5();
    }
}
cs


반응형