본문 바로가기
아카이브/자바의 정석

13장 Thread 20201120

by nineteen 2020. 11. 20.
반응형

쓰레드의 우선순위

- 쓰레드는 우선순위(priority)라는 속성(멤버변수)을 가지고 있음, 이 우선순위 값에 따라 쓰레드가 얻는 실행시간 달라짐

- 쓰레드가 수행하는 작업의 중요도에 따라 쓰레드의 우선순위를 서로 다르게 지정하여 특정 쓰레드가 더 많은 작업시간을 갖도록 할 수 있음

- ex)

파일전송기능이 있는 메신저의 경우, 파일다운로드를 처리하는 쓰레드보다 채팅내용을 전송하는 쓰레드의 우선순위가 더 높아야 사용자가 채팅하는데 불편함이 없을 것

 

1
2
3
4
5
void setPriority(int newPriority)    // 쓰레드의 우선순위를 지정한 값으로 변경
int getPriority()                    // 쓰레드의 우선순위를 반환
public static final int MAX_PRIORITY = 10    // 최대우선순위
public static final int MIN_PRIORITY = 1    // 최소우선순위
public static final int NORM_PRIORITY = 5    // 보통우선순위
cs

 

숫자가 높을수록 우선순위가 높음

쓰레드의 우선순위는 쓰레드를 생성한 쓰레드로부터 상속받음

ex)

main메소드를 수행하는 쓰레드는 우선순위가 5이므로 main메소드내에서 생성하는 쓰레드의 우선순위는 자동적으로 5

 

 

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
// Thread클래스 상속받아 쓰레드 구현
class ThreadEx8_1 extends Thread {
    // run()재정의
    public void run() {    
        for(int i=0; i<300; i++) {
            System.out.print("-");
            for(int x=0; x<10000000; x++);
        }
    }
}
 
// Thread클래스 상속받아 쓰레드 구현
class ThreadEx8_2 extends Thread {
    // run()재정의
    public void run() {
        for(int i=0; i<300; i++) {
            System.out.print("|");
            for(int x=0; x<10000000; x++);
        }
    }
}
 
public class ThreadEx8 {
    public static void main(String[] args) {
        ThreadEx8_1 th1 = new ThreadEx8_1();
        ThreadEx8_2 th2 = new ThreadEx8_2();
        
        th2.setPriority(7);    // 우선순위 지정
        
        System.out.println("Priority of th1(-) : " + th1.getPriority());
        System.out.println("Priority of th2(|) : " + th2.getPriority());
        
        // 쓰레드 시작
        th1.start();
        th2.start();
    }
}
cs

출력

Priority of th1(-) : 5
Priority of th2(|) : 7
-|-|--------------------------------------------------------|||||||||||||||||||||||--------------|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||-----------------------|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||-------------------------||||----------------------------------|||||||--------------------------------------------------------------------------------------------------------------------------------------------------

 

우선순위가 높은 th2가 th1보다 먼저 작업이 끝나는 것을 확인할 수 있다

 

 

 

 

 

 

쓰레드 그룹

- 서로 관련된 쓰레드를 그룹으로 다루기 위함

- 폴더를 생성해서 관련된 파일들을 넣어 관리하는 것 처럼 쓰레드 그룹을 생성해 쓰레드를 그룹으로 묶어 관리 가능

- 모든 쓰레드는 반드시 쓰레드 그룹에 포함되어 있어야 함

- 쓰레드 그룹을 지정하지 않은 쓰레드는 기본적으로 자신을 생성한 쓰레드와 같은 그룹에 속함

 

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 ThreadEx9 {
    public static void main(String[] args) {
        // 쓰레드 그룹생성
        ThreadGroup main = Thread.currentThread().getThreadGroup();    // 쓰레드 자신이 속한 쓰레드 그룹을 반환
        ThreadGroup grp1 = new ThreadGroup("Group1");                // Group1이름의 쓰레드 그룹 생성
        ThreadGroup grp2 = new ThreadGroup("Group2");
        
        // ThreadGroup(ThreadGroup parent, String name)
        ThreadGroup subGrp1 = new ThreadGroup(grp1, "SubGroup1");    // Group1에 포함되는 새로운 쓰레드 그룹 생성
        
        grp1.setMaxPriority(3); // 쓰레드 그룹 grp1의 최대우선순위를 3으로 변경
        
        Runnable r = new Runnable() {
            public void run() {
                try {
                    Thread.sleep(1000);    // 1초 지연
                } catch(InterruptedException e) {}
            }
        };
        
        // Thread(ThreadGroup tg, Runnable r, String name)
        new Thread(grp1, r, "th1").start();
        new Thread(subGrp1, r, "th2").start();
        new Thread(grp2, r, "th3").start();
        
        System.out.println(">>List of ThreadGroup : " + main.getName()     // 쓰레드 그룹의 이름 반환
                    +", Active ThreadGroup: " + main.activeGroupCount()    // 쓰레드 그룹에 포함된 활성상태에 있는 쓰레드 그룹의 수 반환
                    +", Active Thread: " + main.activeCount());            // 쓰레드 그룹에 포함된 활성상태에 있는 쓰레드의 수 반환
        main.list();    // 쓰레드 그룹에 속한 쓰레드와 하위 쓰레드그룹에 대한 정보 출력
    }
}
 
cs

출력

>>List of ThreadGroup : main, Active ThreadGroup: 3, Active Thread: 4

java.lang.ThreadGroup[name=main,maxpri=10]                       

    Thread[main,5,main]

    java.lang.ThreadGroup[name=Group1,maxpri=3]                
        Thread[th1,3,Group1]
        java.lang.ThreadGroup[name=SubGroup1,maxpri=3]

            Thread[th2,3,SubGroup1]

    java.lang.ThreadGroup[name=Group2,maxpri=10]

        Thread[th3,5,Group2]

 

 

 

새로 생성한 모든 쓰레드 그룹은 main쓰레드 그룹의 하위 쓰레드 그룹으로 포함되어 있음

 

 

 

 

 

데몬 쓰레드

- 다른 일반 쓰레드의 작업을 돕는 보조적인 역할을 수행하는 쓰레드

- 일반 쓰레드가 모두 종료되면 데몬 쓰레드는 강제적으로 자동 종료되는데 이는 데몬 쓰레드가 일반 쓰레드의 보조역할을 수행하기 때문

- ex)

가비지 컬렉터, 워드프로세서의 자동저장, 화면자동갱신 등등

- 무한루프와 조건문을 이용해서 실행 후 대기하고 있다가 특정 조건이 만족되면 작업을 수행하고 다시 대기하도록 작성

- 일반 쓰레드의 작성방법과 실행방법이 같고 쓰레드를 생성한 다음 실행하기 전에 setDaemon(true)를 호출하면 됨

- 데몬 쓰레드가 생성한 쓰레드는 자동적으로 데몬 쓰레드가 됨

 

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
// Runnable인터페이스를 구현해 쓰레드 구현
public class ThreadEx10 implements Runnable {
    static boolean autoSave = false;
    
    public static void main(String[] args) {
        Thread t = new Thread(new ThreadEx10());
        t.setDaemon(true);    // 데몬쓰레드로 설정
        t.start();
        
        for(int i=1; i<=10; i++) {
            try {
                Thread.sleep(1000);
            } catch(InterruptedException e) {}
            System.out.println(i);
            
            if(i==5)
                autoSave = true;
        }
    }
    // Runnable의 run()구현
    public void run() {
        while(true) {
            try {
                Thread.sleep(3*1000);    // 3초
            } catch(InterruptedException e) {}
            if(autoSave) {
                autoSave();
            }        
        }
    }
    
    public void autoSave() {
        System.out.println("작업파일이 자동저장되었습니다.");
    }
}
cs

출력

1
2
3
4
5
작업파일이 자동저장되었습니다.
6
7
8
작업파일이 자동저장되었습니다.
9
10

 

 

16행에 의해 autoSave가 true가 되고, 3초마다 autoSave()를 실행