본문 바로가기

Programming/국비학원

220516 - API 확인문제, 멀티 스레드(스레드 생성, 우선순위, 동기화 메소드, 상태)

API 확인문제
  • 6번 문제
1
2
3
4
5
6
7
8
9
10
11
public class BytesToStringEx {
 
    public static void main(String[] args) {
 
        byte[] bytes = {73,32,108,111,118,101,32,121,111,117};
        String str = new String(bytes);
        System.out.println(str);
        
    }
 
}
cs

//
I love you

 

 

  • 7번 문제
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class FindAndReplaceEx {
 
    public static void main(String[] args) {
 
        String str = "모든 프로그램은 자바 언어로 개발될 수 있다.";
        int index = str.indexOf("자바");  //문자열의 위치값 리턴
        if (index==-1) {
            System.out.println("자바 문자열이 포함되어 있지 않습니다.");
        }else {
            System.out.println("자바 문자열이 포함되어 있습니다.");
            str = str.replace("자바""java");
            System.out.println("->"+str);
        }
 
    }
 
}
cs

//

자바 문자열이 포함되어 있습니다.
-> 모든 프로그램은 java 언어로 개발될 수 있다.

 

 

  • 8번 문제
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import java.util.StringTokenizer;
 
public class SplitEx {
 
    public static void main(String[] args) {
        
        String str = "아이디,이름,패스워드";
        
        //방법1 split() 메소드 => 여러 구분자 가능
        String[] member = str.split(","); 
        for (String m:member) {
            System.out.println(m);
        }
        
        //방법2 StringTokenizer => 단일 구분자만
        System.out.println();
        StringTokenizer token = new StringTokenizer(str,",");
        while(token.hasMoreTokens()) {  
            String m = token.nextToken();  
            System.out.println(m);
        }
        
    }
cs

//

아이디

이름

패스워드

 

 

  • 9번 문제
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class StringBuilderEx {
 
    public static void main(String[] args) {
 
        String str = "";
        for (int i=1;i<=100;i++) {
            str+=i;
        }
        System.out.println(str);
        
        //개선 코드 작성
        System.out.println();
        StringBuilder sb = new StringBuilder();
        for (int i=1;i<=100;i++) {
           sb.append(i);  
        }
        str = sb.toString()
        System.out.println(str);
        
    }
 
}
cs

//

123456789101112~100

 

 

  • 10번 문제
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import java.util.regex.Pattern;
 
public class PatternMatcherEx {
 
    public static void main(String[] args) {
        String id = "D2l2j4348964";
        String regExp = "[A-Za-z][A-Za-z_0-9]{7,11}";
        
        boolean isMatch = Pattern.matches(regExp, id);
        if(isMatch) {
            System.out.println("ID 사용 가능");
        }else {
            System.out.println("ID 사용 불가");
        }
 
    }
 
}
cs

//
ID 사용 가능

 

 

  • 11번 문제
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class IntegerCompareEx {
 
    public static void main(String[] args) {
        Integer obj1=100;
        Integer obj2=100;
        Integer obj3=300;
        Integer obj4=300;
        
        System.out.println(obj1==obj2);
        System.out.println(obj3==obj4)  ; //객체 => equals 로 비교해야 함
        
    }
 
}
cs

//
true  => -128~127 범위 내 byte, short, int는 ==연산자로도 비교 가능 / boolean, char(\u0000~007f)도
false

 

 

  • 12번 문제
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class StringConvertEx {
 
    public static void main(String[] args) {
 
        String str1 = "200";
        int int1 = Integer.parseInt(str1); //String -> int
        System.out.println(int1);
        
        int int2 = 150;
        String str2 = String.valueOf(int2); //int -> String
        System.out.println(str2);
    }
 
}
cs

 

 

  • 13번 문제
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import java.text.SimpleDateFormat;
import java.util.Date;
 
public class DatePrintEx {
 
    public static void main(String[] args) {
 
        Date now = new Date();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy년 MM월 dd일 E요일 hh시 mm분");
        System.out.println(sdf.format(now));
        
    }
 
}
cs

 

 

 

멀티 스레드

: 하나의 애플리케이션 안에서 여러가지 동작을 동시에 실행하도록 함 (=앱 내부의 멀티태스킹)


= 한 프로세스 내 스레드 두 개 => 두개의 코드 실행 흐름
=> 하나의 프로세스 내부에 생성 => 한 스레드가 예외 -> 프로세스 종료 -> 다른 스레드 영향
= 병렬 작업 처리 (=실제로는 동시가 아닌 A,B 왔다갔다 처리함)

메인 메소드 = 메인 스레드

cf. 멀티 프로세스 : 운영체제에서 할당받은 각각의 메모리 => 프로세스들은 서로 독립적
멀티프로세스⊃프로세스1⊃멀티 스레드
                 ⊃프로세스2⊃싱글 스레드

 


주기억장치 - RAM (메모리)
보조기억장치 - 하드디스크
중앙처리장치 - CPU

 

 

  • 작업 스레드 생성

 

  • 스레드 생성 전
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
import java.awt.Toolkit;
 
public class ThreadEx1 {
 
    public static void main(String[] args) {
        
        Toolkit toolkit = Toolkit.getDefaultToolkit(); //객체 생성, static
        for (int i=1;i<=5;i++) {
           toolkit.beep(); //비프음 발생
            try {
                Thread.sleep(500); //0.5초 일시정지(ms) //try, catch문 필수
            } catch (InterruptedException e) {
            }  
        }//for
        
        for (int i=1;i<=5;i++) {
            System.out.println("띵!!");
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
            }  
        }
        
    }
 
}
cs

=> 2개 for문 순차 실행

 

 

  • 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
import java.awt.Toolkit;
 
public class ThreadEx1 {
 
    public static void main(String[] args) {
       //작업 스레드
        Thread thread = new Thread(new Runnable() {  
        //스레드 생성시 Runnable 인터페이스 사용
//Runnable 내 run() 메소드 - 작업스레드 실행 코드
            
            @Override
            public void run() {
                Toolkit toolkit = Toolkit.getDefaultToolkit(); 
                for (int i=1;i<=5;i++) {
                    toolkit.beep(); 
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                    }  
                }//for
            }
        });
        thread.start();  
        //스레드 시작 or 실행 대기 상태(다른 스레드 실행 시)
 
       //메인 스레드
        for (int i=1;i<=5;i++) {
            System.out.println("띵!!");
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
            }  
        }
        
    }
 
}
cs
 
 
 

//
띵!!
띵!!
띵!!
띵!!
띵!!
=> 소리, 숫자 동시 실행

 

 

  • Thread 클래스로부터 직접 생성 - 인터페이스 구현클래스 사용
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import java.awt.Toolkit;
 
public class BeepTask implements Runnable {
 
    @Override
    public void run() {
        
        Toolkit toolkit = Toolkit.getDefaultToolkit(); 
        for (int i=1;i<=5;i++) {
            try {
                toolkit.beep(); 
                Thread.sleep(500);
            } catch (InterruptedException e) {
            }  
        }//for
 
    }
    
}
cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import java.awt.Toolkit;
 
public class ThreadEx2 {
 
    public static void main(String[] args) {
       //작업 스레드
        Runnable bt = new BeepTask();
        //다형성 => Beeptask 생성, Runnable로 선언 => Runnable 내 메소드만 실행됨
        Thread thread = new Thread(bt);
        thread.start();
        
//메인 스레드
        for (int i=1;i<=5;i++) {
            System.out.println("띵!!");
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
            }  
        }
        
    }
 
}
cs

 

 

  • Thread 하위클래스로부터 생성 - 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
public class BeepThread extends Thread {
    @Override
    public void run() {
        
        Toolkit toolkit = Toolkit.getDefaultToolkit(); 
        for (int i=1;i<=5;i++) {
            try {
                toolkit.beep(); 
                Thread.sleep(500);
            } catch (InterruptedException e) {
            }  
        }//for
    }
 
}
 
 
public class ThreadEx3 {
 
    public static void main(String[] args) {
        //BeepThread(비프음) 작업 스레드
        Thread thread = new BeepThread();
        thread.start();
        
        //메인 스레드 (콘솔 출력)
        for (int i=1;i<=5;i++) {
            System.out.println("띵!!");
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
            }  
        }
        
    }
 
}
cs

 

 

  • 익명 스레드
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
import java.awt.Toolkit;
 
public class ThreadEx1 {
 
    public static void main(String[] args) {
    
    //익명 스레드    
    new Thread(new Runnable() { 
            
            @Override
public void run() {
                Toolkit toolkit = Toolkit.getDefaultToolkit(); 
                for (int i=1;i<=5;i++) {
                    try {
                        toolkit.beep(); 
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                    }  
                }//for
            }
        }).start();    
        
        //메인 스레드
        for (int i=1;i<=5;i++) {
            System.out.println("띵!!");
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
            }  
        }
        
    }
 
}
cs

 

 

  • 스레드 이름

스레드 생성 시 자동적으로 "Thread-n" 

=> Thread 클래스 setName() 메소드로 변경 (cf. getName() 으로 이름 전달받음)

 

setName(), getName() => Thread의 인스턴스 메소드 => 스레드 객체 참조 필요

객체 참조 X => Thread 정적 메소드 currentThread() 사용해 현재 실행되는 스레드 참조 얻기 가능

 

 

  •  
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
public class ThreadA extends Thread{
    //생성자
    public ThreadA() {
        setName("ThreadA");  //인스턴스 메소드
    }
    
    @Override
    public void run() {
        for (int i=1;i<=5;i++) {
            System.out.println(getName()+"가 한 작업");
        }
    }
    
}
 
 
public class ThreadB extends Thread {
 
    //기본 생성자
    
    @Override
    public void run() {
        for (int i=1;i<=5;i++) {
            System.out.println(getName()+"가 한 작업"); //Thread-1
        }
    }
    
}
 
 
public class ThreadEx4 {
 
    public static void main(String[] args) {
        
        Thread mainThread = Thread.currentThread();  
        //코드 실행하는 현재 스레드의 참조객체 얻음  //현재의 스레드가 무엇인지 확인
        System.out.println("프로그램 시작 스레드 이름 : "+ mainThread);

        ThreadA ta = new ThreadA();  //스레드 생성
        System.out.println("작업 스레드 이름 : "+ta.getName());
        ta.start();

        ThreadB tb = new ThreadB();
        System.out.println("작업 스레드 이름 : "+tb.getName());
        tb.start();
        
    }
 
}
cs

//
프로그램 시작 스레드 이름 : Thread[main,5,main]
작업 스레드 이름 : ThreadA
ThreadA가 한 작업
ThreadA가 한 작업
ThreadA가 한 작업
ThreadA가 한 작업
ThreadA가 한 작업
작업 스레드 이름 : Thread-1
Thread-1가 한 작업
Thread-1가 한 작업
Thread-1가 한 작업
Thread-1가 한 작업
Thread-1가 한 작업

 

 

  • 스레드 우선순위
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
public class CalThread extends Thread{
    //생성자
    public CalThread(String name) {
        setName(name);  //스레드 이름 변경
    }
    
    @Override
    public void run() {  //스레드 실행 내용
        for (int i=0;i<2100000000;i++) {
            
        }
        System.out.println(getName());
    }
    
}
 
 
public class PriorityEx1 {
 
    public static void main(String[] args) {
 
        for (int i=1;i<=10;i++) {
            Thread thread = new CalThread("계산 작업 "+i);
            if (i==7) {
                thread.setPriority(Thread.MAX_PRIORITY);
            }else {
                thread.setPriority(Thread.MIN_PRIORITY);
            }
            thread.start();
        }//for
        
    }
 
}
cs

//

계산 작업 9
계산 작업 2
계산 작업 10
계산 작업 7  => 반복 숫자 낮아서 각각 하나씩 돌아가는데 차이가 별루 없음
계산 작업 1
계산 작업 5
계산 작업 4
계산 작업 3
계산 작업 8
계산 작업 6
=> 랜덤하게 바뀜

 

 

=> 수정

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
public class CalThread extends Thread{
    //생성자
    public CalThread(String name) {
        setName(name);  //스레드 이름 변경
    }
    
    @Override
    public void run() {  //스레드 실행 내용
        for (long i=0;i<1100000000L;i++) {
            
        }
        System.out.println(getName());
    }
    
}
 
 
public class PriorityEx1 {
 
    public static void main(String[] args) {
 
        for (int i=1;i<=10;i++) {
            Thread thread = new CalThread("계산 작업 "+i);
            if (i==7) {
                thread.setPriority(Thread.MAX_PRIORITY);
            }else {
                thread.setPriority(Thread.MIN_PRIORITY);
            }
            thread.start();
        }//for
        
    }
 
}
cs

//

계산 작업 7
계산 작업 8
계산 작업 3
계산 작업 4
계산 작업 2
계산 작업 10
계산 작업 6
계산 작업 9
계산 작업 5
계산 작업 1
=> 7이 1순위로 끝남

 

 

  • 동기화 메소드 (synchronzied)

: 2개 이상의 스레드가 클래스 공유할 때 => 사용 중인 스레드 작업이 끝날 때까지 객체 잠금

 

멀티스레드 => 스레드들 객체 공유, 작업 多

 

cf. 동기화 블록 (동기화 메소드가 더 활용도 높음)
void method(){
  ..
  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
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
public class UserJob1 extends Thread {
 
    //객체 필드
    private Calculator calc;  // user1 & user2 계산기 공유
 
    public void setCalc(Calculator calc) {
        this.setName("UserJob1");
        this.calc = calc;
    }
 
    @Override
    public void run() {
        calc.setMemory(100);
    }
 
}
 
 
public class UserJob2 extends Thread {
 
//객체 필드
    private Calculator calc;  // user1 & user2 계산기 공유
 
    public void setCalc(Calculator calc) {
        this.setName("UserJob2");
        this.calc = calc;
    }
 
    @Override
    public void run() {
        calc.setMemory(50);
    }
 
}
 
 
public class Calculator {
        
        private int memory;  // 접근제한 -> getter, setter 필요
 
        public int getMemory() {
            return memory;
        }
 
        public void setMemory(int memory) {
            this.memory = memory;
            try {
                Thread.sleep(2000);  //2초
            } catch (InterruptedException e) {  //튕김 현상 예외 처리
                
            } 
            System.out.println(Thread.currentThread().getName()+" : "+this.memory);
            //현재 실행하고 있는 스레드의 이름
        }
        
}
 
 
public class CalculatorEx1 {
 
    public static void main(String[] args) {
        
        Calculator calc = new Calculator();  //인스턴스 객체 생성
        
UserJob1 job1 = new UserJob1();  //스레드 생성
        job1.setCalc(calc);
        job1.start();
        
        UserJob2 job2 = new UserJob2();  //스레드 생성
        job2.setCalc(calc);
        job2.start();
        
    }
 
}
cs

//
UserJob2 : 50
UserJob1 : 50 => 1번 스레드 실행 중에 2번 스레드 실행돼 오류

 

 

=> 해결 : Calculator 클래스 동기화 메소드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class Calculator {
        
        private int memory;  
 
        public int getMemory() {
            return memory;
        }
 
        public synchronized void setMemory(int memory) {    
            this.memory = memory;
            try {
                Thread.sleep(2000); 
            } catch (InterruptedException e) {  
                
            } 
            System.out.println(Thread.currentThread().getName()+" : "+this.memory);
 
        }
        
}
cs

=> 예제 실행 시

UserJob1 : 100
UserJob2 : 50

 

 

  • 스레드 상태

Thread 클래스의 getState() => 스레드 상태 얻어옴

ex. NEW, RUNNABLE(실행 또는 실행대기상태), TIME_WAITING(sleep), BLOCKED(동기화블록으로 잠금됨), TERMINATED(실행 마침)

 

 

  •  
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
public class TargetThread extends Thread{
    
    @Override
    public void run() {
        //작업 1
        for (long i=0;i<3100000000L;i++) {
            
        }
        //1초 일시정지
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {}
        //작업 2
        for (long i=0;i<3100000000L;i++) {
            
        }
    }
 
}
 
 
public class StatePrintThread extends Thread {
 
    private Thread target;
    
    public StatePrintThread(Thread target) {
        this.target=target;
    }
    
    @Override
    public void run() {
        while(true) {
            Thread.State state = target.getState();
           
            System.out.println("타겟 스레드 상태 "+state);
            if (state==Thread.State.NEW) {  //스레드 생성 상태 => 생성
                target.start();
            }
            if(state==Thread.State.TERMINATED) {  //스레드 마침 => while 탈출
                break;
            }
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
            }
 
        }
    }
    
}
 
 
public class ThreadStateEx1 {
 
    public static void main(String[] args) {
        
        StatePrintThread stateThread = new StatePrintThread(new TargetThread());  //익명
        stateThread.start();
    }
 
}
cs

//

타겟 스레드 상태 NEW
타겟 스레드 상태 RUNNABLE
타겟 스레드 상태 RUNNABLE
타겟 스레드 상태 TIMED_WAITING
타겟 스레드 상태 TIMED_WAITING
타겟 스레드 상태 RUNNABLE
타겟 스레드 상태 RUNNABLE
타겟 스레드 상태 TERMINATED