728x90

유클리드 호제법을 사용하면 O(logN)까지 줄일 수 있다.

 

1071과 1029의 최대공약수를 구하면,

  • 1071은 1029로 나누어떨어지지 않기 때문에, 1071을 1029로 나눈 나머지를 구한다. ≫ 42
  • 1029는 42로 나누어떨어지지 않기 때문에, 1029를 42로 나눈 나머지를 구한다. ≫ 21
  • 42는 21로 나누어떨어진다.

따라서, 최대공약수는 21이다.

 

최소 공배수는 1071*1029 / 두수의 최대 공약수 이다.

import java.io.*;
import java.util.StringTokenizer;

public class Main {
    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
        StringTokenizer st = new StringTokenizer(br.readLine());
        int p = Integer.parseInt(st.nextToken());
        int q = Integer.parseInt(st.nextToken());
        int gcd = GCD(p,q);
        bw.write(gcd+"\n"+(p*q)/gcd);
        bw.close();
    }
    static int GCD(int p, int q)
    {
        if(p < q){
            int tmp = p;
            p = q;
            q = tmp;
        }
        if(q == 0)
            return p;
        return GCD(q,p%q);
    }
}
728x90
728x90

Obj. 자바의 Input과 Output에 대해 학습.

Todo.

13-1. 스트림 (Stream) / 버퍼 (Buffer) / 채널 (Channel) 기반의 I/O

13-2. InputStream과 OutputStream

13-3. Byte와 Character 스트림

13-4. 표준 스트림 (System.in, System.out, System.err)

13-5. 파일 읽고 쓰기


13-1. 스트림 (Stream) / 버퍼 (Buffer) / 채널 (Channel) 기반의 I/O

- 스트림 :

  • FIFO(First In First Out)
  • 단방향 이기 때문에 입력 스트림과 출력 스트림을 별도로 사용해야 한다.
  • 연속된 데이터의 흐름으로 입출력 진행 시 다른 작업을 할 수 없는 블로킹(Blocking) 상태가 된다.
  • 입출력 대상을 변경하기 편하고 동일한 프로그램 구조를 유지할 수 있다.

- 버퍼 : 

  • byte, char, int 등 기본 데이터 타입을 저장할 수 있는 저장소로서, 배열과 마찬가지로 제한된 크기에 순서대로 데이터를 저장한다.
  • 버퍼는 데이터를 저장하기 위한 것이지만, 실제로 버퍼가 사용되는 것은 채널을 통해 데이터를 주고 받을 때 쓰인다.
  • 채널을 통해서 소켓, 파일 등에 데이터를 전송할 때나 읽어올 때 버퍼를 사용하여 시스템 콜의 횟수를 줄여 주기에 서버의 성능이 증가한다

- 채널 :

  • 데이터가 통과하는 쌍방향 통로이며, 채널에서 데이터를 주고 받을 때 사용되는 것이 버퍼이다. 
  • 채널에는 소켓과 연결괸 SocketChannel, 파일과 연결된 FileChannel, 파이프와 연결된 Pipe.SinkChannel 과 Pipe.SourceChannel 등이 존재하며, 서버소켓과 연결된 ServerSocetChannel 도 존재한다.

- NIO (New I/O)  : 자바 1.4 버전부터 추가된 API로 넌블로킹 처리가 가능하며, 스트림이 아닌 채널을 사용한다.

  • NIO는 비동기 방식을 지원하여, 연결 클라이언트가 많고, IO처리가 작은 경우 자주 사용된다.

 

13-2. InputStream과 OutputStream

- InputStream 

  • 바이트 기반 입력 스트립의 최상위 추상 클래스
  • 모든 바이트 기반 입력 스트림은 이 클래스를 상속 받아서 만들어 진다.
  • 버퍼, 파일, 네트워크 단에서 입력되는 데이터를 읽어오는 기능을 수행한다.

- OutputStream

  • 바이트 기반 출력 스트림의 최상위 추상 클래스
  • 모든 바이트 기반 출력 스트림은 이 클래스를 상속 받아서 만들어 진다.
  • 버퍼, 파일, 네트워크 단으로 데이터를 내보내는 기능을 한다.
  • 메서드 중 flush() 를 해야만 버퍼에 잔류하는 모든 바이트를 출력한다.

13-3. Byte와 Character 스트림

- Byte Stream

  • 바이너리 데이터를 입출력 하는 스트림
  • 데이터는 1바이트(8비트) 단위로 처리
  • 이미지, 동영상 등을 송수신 할 떄 주로 사용

- Character Stream

  • 텍스트 데이터를 입출력하는 스트림
  • 데이터는 2바이트 단위로 처리
  • 일반적인 텍스트 및 JSON, HTML 등을 송수신할 때 주로 사용

- 보조 스트림

  • FilterInputStream & FilterOutputStream 은 상속받은 클래스들로 부터 기본 스트림과 결합하여 특정 상황에서 보다 편리하게 사용할 수 있다.
  • BufferedInputStream & BufferedOutputStream 은 버퍼를 사용해 입출력 효율과 편의를 위해 사용.
  • BufferedReader & BufferedWriter 은 라인단위의 입출력이 편함
  • InputStreamReader & OutputStreamWriter 은 바이트 스트림을 문자 스트림 처럼 쓸 수 있도록 하며 문자 인코딩 변환을 지원한다.
  • DataInputStream & DataOutputStream : 자바 원시자료형 데이터 처리에 적합하다.

13-4. 표준 스트림 (System.in, System.out, System.err)

  • 표준 입출력 스트림의 종류는 java.lang 패키지의 System 클래스 내부에 static 으로 선언되어 있다.
publoc final class System{

 	public static final InputStream in;
    public static final PrintStream out;
    public static final PrintStream err;
   ...
  }

- out, err는 둘다 출력 스트림이며, err는 버퍼링을 지원하지 않는다. err가 보다 정확하고 빠르게 출력되어야 하기 때문.

13-5. 파일 읽고 쓰기

- 텍스트 파일인 경우 문자 스트림 클래스들을 사용하면 되고, 바이너리 파일인 경우 바이트 스트림을 기본적으로 사용한다.

- 입출력 효율을 위해  Buffered 계열의 보조 스트림을 함께 사용하는 것이 좋다.

- 텍스트 파일인 경우

BufferedReader br = new BufferedReader(new FileReader("a.txt"));
BufferedWriter bw = new BufferedWriter(new FileWriter("b.txt"));
String s;
while ((s = br.readLine()) != null) {
    bw.write(s + "\n");
}

- 이진 파일인 경우

BufferedInputStream is = new BufferedInputStream(new FileInputStream("a.jpg"));
BufferedOutputStream os = new BufferedOutputStream(new FileOutputStream("b.jpg"));
byte[] buffer = new byte[16384];
while (is.read(buffer) != -1) {
    os.write(buffer);
}

Reference

bingbingpa.github.io/java/whiteship-live-study-week13/

728x90

'Java > [Whiteship]자바스터디' 카테고리의 다른 글

12주차 과제 : 애노테이션  (0) 2021.03.01
11주차 과제 : Enum  (0) 2021.02.28
10주차 과제 : 멀티쓰레드 프로그래밍  (0) 2021.01.27
9주차 과제 : 예외  (0) 2021.01.21
8주차 과제 : 인터페이스  (0) 2021.01.19
728x90

Obj. 자바의 애노테이션에 대해 학습.

Todo.

12-1.애노테이션 정의하는 방법

12-2. @retention

12-3. @target

12-4. @documented

12-5. 애노테이션 프로세서


12-1.애노테이션 정의하는 방법

애노테이션이란? 애노테이션은 주석이라는 뜻을 가지고 있다. 기본적으로 // or /**/와 같이 생겼으나 주석과는 다르다.

- 어노테이션의 역할도 주석과 크게 다르지 않다.

- 일반주석과 큰 차이점은 코드를 작성할 수 있다는 점이다.

- 코드를 작성할 수 있다는 뜻은 어노테이션으로 뭔가를 할 수 있다.

 

특징

- @interface 으로 정의할 수 있다.

- 상속 할 수 없다. -> 이미 java.lang.annotation.Annotation 인터페이스를 상속 받음.

- 제네닉 타입 선언을 할 수 없다.

- 매서드는 매개변수를 가질 수 없다.

- 매서드 선언은 throws 절을 가질 수 없다.

- 추상 메서드를 가지고 있다.

- 추상 메서드를 구현하지 않아도 컴파일러가 자동으로 구현 해준다.

애노테이션에 다이나믹하게 실행되는 코드는 들어가지 않는다.

- 런타임 중에 알아내야 하는 값은 못 들어간다.

@interface 애노테이션_이름 {
	Type Element 이름();
    Type Element 이름() default value;
    }

여기서 value는 null은 불가능 하다.

또한 타입은 기본형, String, enum, Annotation, class만 혀용된다.

 

표준 애노테이션 

- @Override : 컴파일러에게 오버라이팅하는 메서드 라는 것을 알려준다.

- @Deprecated : 앞으로 사용하지 않을 것을 권장하는 대상에 붙인다.

- @SuppressWarnings : 컴파일러의 특정 경고메세지가 나타나지 않게 해준다.

- @SafeVarargs : 제네릭 타입의 가변인자에 사용한다.(1.7)

- @FunctionalInterface : 함수형 인터페이스 라는 것을 알림(1.8)

- @Native : native 메서드에서 참조되는 상수 앞에 붙인다(1.8)

메타 애노테이션 (애너테이션을 정의하는데 사용하는 애너테이션)

- @Target : 애노테이션이 적용가능한 대상을 지정하는데 사용

- @Documented : 애노테이션 정보가 javadoc으로 작성된 문서에 포함되게 한다.

- @Inherited : 애노테이션이 자손 클래스에 상속되도록 한다.

- @Retention : 애노테이션이 유지되는 범위를 지정하는데 사용

- @Repeatable : 애노테이션을 반복해서 사용 할 수 있게 한다(1.8)

 

12-2. @retention

애노테이션 유지되는 기간을 지정하는데 사용한다.

@Retention(RetentionPolict.SOURCE)
@Retention(RetentionPolict.CLASS)
@Retention(RetentionPolict.RUNTIME)

유지정책

- SOURCE : 소스 코드에만 유지 -> 컴파일 시에만 사용하고, 컴파일 후에는 무시

- CLASS : 클래스 파일까지 유지한다. 즉 바이트 코드에 남기겠다.

- RUNTIME : CLASS와 유사하지만, 메모리에 적재된 클래스 정보를 읽어올 때 애노테이션 정보를 그대로 포함한다.

12-3. @target

애노테이션이 적용 가능한 대상을 지정하는데 사용된다.

여러 개의 값을 지정할 때는 배열처럼 괄호{}를 이용해서 지정할 수 있다.

@Target({TYPE, FIELD, METHOD, PARAMETER, CONSTRUCTOR, LOCAL_VARIABLE})
@Target(ElementType.Type)}

  대상 타입 종류

- ANNOTATION_TYPE : 애노테이션

- CONSTRUCTOR : 생성자

- FIELD : 필드(멤버 변수, ENUM 상수)

- LOCAL_VARIABLE : 지역 변수

- METHOD : 메서드

- PACKAGE : 패키지

- PARAMETER : 매개 변수

- TYPE : 타입(클래스, 인터페이스, enum)

- TYPE_PARAMETER : 타입 매개션수(1.8)

- TYPE_USE : 타입이 사용되는 모든 곳(1.8)

 

12-4. @documented

애노테이션에 대한 정보가 javadoc으로 작성한 문서에 포함되도록 한다.

표준 애노테이션 중  Override와 SuppressWarnings를 제외하고 모두  Documented 메타 애노테이션이 붙어 잇다.

 

 

12-5. 애노테이션 프로세서

애노테이션 프로세서는 소스코드 레벨에서 소스코드에 붙어있는 애노테이션을 읽어서 컴파일러가 컴파일 하는 중에 새로운 소스코드를 생성하거나 기존 소스코드를 바꿀 수 있다. 또는, 클래스(바이트코드)도 생성 할 수 있고 별개의 리소스 파일을 생성할 수 있는 강력한 기능이다.

 

장점 

- 바이트코드에 대한 조작은 런타임에 발생되는 조작임으로 런타임에 대한 비용이 발생한다.

- 하지만 애노테이션 프로세서는 애플리케이션을 구동하는 런타임 시점이 아니라 컴파일 시점에 조작하여 런타임에 대한 비용이 제로가 된다.

 

단점 : 기존의 코드를 고치는 방법은 현재로써는 public 한 API가 없다.

 

 

 

Reference

 https://www.geeksforgeeks.org/annotations-in-java/

www.notion.so/37d183f38389426d9700453f00253532

728x90

'Java > [Whiteship]자바스터디' 카테고리의 다른 글

13주차 과제 : I/O  (0) 2021.03.29
11주차 과제 : Enum  (0) 2021.02.28
10주차 과제 : 멀티쓰레드 프로그래밍  (0) 2021.01.27
9주차 과제 : 예외  (0) 2021.01.21
8주차 과제 : 인터페이스  (0) 2021.01.19
728x90

Obj. 자바의 열거형에 대해 학습.

Todo.

11-1. enum 정의하는 방법

11-2. enum이 제공하는 메소드(values() 와 valueOf())

11-3. java.lang.Enum

11-4. EnumSet


11-1. enum 정의하는 방법

자바에서는 Enum을 '열거형' 또는 Enumeration 또는 상수 집합이라고 한다.

멤버라 불리는 명명된 값의 집합을 이루는 자료형이다.

언어의 상수 역할을 하는 식별자이다.

enum은 각 클래스를 인스턴스화 시킨 것이다.

 

네임 스페이스 기법을 활용해서 상수의 종류를 늘려 주지만, 많은 조건이 들어 올 수록 변수 명이 복잡해 질 것이다.

이를 보완하기 위해 Enum을 활용하여 상수를 만들어 준다. 단, 다른  Enum간에는 비교를 할 수 없다.

일반적인 선언 방법은 아래와 같다.

enum Day{ //일반적으로 0부터 연속적인 정수 값을 부여한다.
	Sun, Mon, Tue, Wen, Thu, Fri, Sat;
    }

값을 가진 Enum 상수

enum 열거형 이름 {
	상수명(), 상수명(), 상수명();
    
    private final [DATA TYPE] [DATA NAME];
    
    public getDataName(){
    	return DataName;
    }
    private 생성자( 매개변수 ..){
    	변수 = 값;
    }
}
        

다중 값을 가진 Enum 상수

getter 함수를 활용해서 값을 꺼내오면 된다.

또한 메서드 오버라이딩을 할 수 있다.

enum Data{
	A("A Value", 1),
    B("B Value", 2),
    C("C Value", 3);
    
    private final String value;
    private final int num;
    
    Data(String value, int num)
    {
    	this.value = value;
        this.num = num;
    }
	public String getvalue(){
    	return value;
        }
	public int getnum(){
    	return num;
        }
}

11-2. enum이 제공하는 메소드(values() 와 valueOf())

- values()  : 열거형의 모든 상수를 배열에 담아 반환한다.

- valueOf(String name): 열거형 상수의 이름으로 문자열 상수에 대한 참조를 얻을 수 있게 해준다.

컴파일러가 자동으로 추가해주는 메소드 이다.

- name( ) : 열거형 상수의 이름을 문자열로 반환한다.

- ordinal( ) : 열거형 상수가 정의된 순서(0부터 시작)를 정수로 반환한다.

- toString( ) : 열거형 상수의 이름을 문자열로 반환한다.

- compareTo( ) : 정렬의 기준을 위한 메소드로 비교 대상보다 순서가 빠르면 -1, 같으면 0, 느리면 1을 반환한다.

- valueOf(enumType, name) : 지정된 열거형에서 name과 일치하는 열거형 상수를 반환한다.

- getDeclaringClass( ) : 열거형의 Class 객체를 반환한다.

- values( ) : 열거형의 모든 상수를 배열에 담아 반환한다.

 

name 과 toString의 차이는 Override 가 가능한지 의 차이다. name은 불가능!

 

11-3. java.lang.Enum

Enum 클래스는 모두 java 언어 열거타입의 상위 클래스이다. 따라서 단일 상속만 허용되는 자바이기에 enum은 별도의 상속을 받을 수 없다.

 

 

11-4. EnumSet

열거형 타입과 함께 사용하기 위한 특별한 Set 구현체이다. EnumSet은 비트연산을 이용해 메모리 공간도 적게 차지하고, 속도도 빠르다. 또한, Set 기반이지만 enum과 static 타입의 메소드들로 구성되어 있어, 안정성을 최대한 추구하면서도 편리한 사용이 가능하다.

 

주의사항

생성자 오버라이딩이 불가능하고 동일한 타입의 열거 상수만 선언 가능.

null  값을 넣거나 NullPointerException을 던질 수 없다.

스레드로부터 안전하지 않으므로 필요한 경우 외부에서 동기화 해야한다.

상수는 열거 형에 선언 된 순서에 따라 저장된다.(ordinal 변수)

복사본에서는  Fail-Safe 방식의 Iterator를 사용한다.

 

allOf(Class elementType): 지정한 Type의 모든 원소를 포함하는 EnumSet을 만든다.

clone() : 이 집합의 복사본을 반환한다.

complementOf(EnumSet s) : 지정한 EnumSet에 포함되지 않은 원소만 갖는 동일한 Type의 EnumSet을 만든다.

copyOf(Collection c) : 지정한 Collection에서 초기화된 EnumSet을 만든다.

copyOf(EnumSet s) : 지정한 EnumSet과 동일한 Type을 가진 EnumSet을 만든다. 이 때, 처음과 동일한 원소(원소가 있는 경우)를 포함한다.

noneOf(Class elementType) : 지정한 Type을 가지는 빈 EnumSet을 만든다.

of(E e), of(E first, E… rest), of(E e1, E e2) : 지정한 원소(또는 원소들)를 포함하는 EnumSet을 만든다.

range(E from, E to) : 지정된 두 원소 사이에 있는 모든 원소를 포함하는 EnumSet을 만든다.

 

 

Reference

velog.io/@kwj1270/Enum

wisdom-and-record.tistory.com/52

b-programmer.tistory.com/262

yadon079.github.io/2021/java%20study%20halle/week-11

 

728x90

'Java > [Whiteship]자바스터디' 카테고리의 다른 글

13주차 과제 : I/O  (0) 2021.03.29
12주차 과제 : 애노테이션  (0) 2021.03.01
10주차 과제 : 멀티쓰레드 프로그래밍  (0) 2021.01.27
9주차 과제 : 예외  (0) 2021.01.21
8주차 과제 : 인터페이스  (0) 2021.01.19
728x90

프로그래머스 2021 KAKAO BLIND RECRUITMENT 2번 문제 메뉴 리뉴얼

처음 문제를 풀때 반대의 방향으로 접근을 하여 시간이 더욱 소요 되었다. 

 

먼저 이 문제는 부르트포스 알고리즘을 통해 해결한다.

 

주문한 모든 메뉴들의 조합을 각각 구한 뒤, 기록을 해두고 가장 많은 조합을 찾으면 된다.

생각보다 단순한 논리였다.

 

import java.util.*;

class Solution {
      HashMap<String, Integer> hashMap = new HashMap<>();

    public String[] solution(String[] orders, int[] course) {

        ArrayList<String> before = new ArrayList<>(); // 초기화
        StringBuilder sb = new StringBuilder();

        for (String menu : orders) {
            char[] tmp = menu.toCharArray();
            Arrays.sort(tmp);
            for (int i : course) {
                Comb(tmp, sb, 0, 0, i);
            }
         } // 각각의 조합을 만들어 둠.

        for (int i : course) {
            Set<Map.Entry<String, Integer>> entry2 = hashMap.entrySet();

            int max = 0;
            for (Map.Entry<String, Integer> entry : entry2) {
                if (entry.getKey().length() == i) {
                    max = Math.max(max, entry.getValue());
                }
            }
            for (Map.Entry<String, Integer> entry : entry2) {
                if (max > 1 && entry.getValue() == max && entry.getKey().length() == i)
                    before.add(entry.getKey());
            }
        }

        Collections.sort(before);
        String[] answer = new String[before.size()];

        for (int i = 0; i < before.size(); i++) {
            answer[i] = before.get(i);
        }

        return answer;
    }

    public void Comb(char[] order, StringBuilder sb, int start, int n, int r) {
        if (n == r) {
            hashMap.put(sb.toString(), hashMap.getOrDefault(sb.toString(), 0) + 1);
            return;
        }
        for (int i = start; i < order.length; i++) {
            sb.append(order[i]);
            Comb(order, sb, i + 1, n + 1, r);
            sb.delete(n, n + 1);
        }
    }
}
728x90

'알고리즘 > 프로그래머스' 카테고리의 다른 글

프로그래머스 신규 아이디 추천 - Java  (0) 2021.02.01
728x90

프로그래머스 2021 KAKAO BLIND RECRUITMENT 1번 문제 신규 아이디 추천

 

이 문제는 여러 방법이 있으나, 직접 구현하는 방법을 사용했다.

 

여기서 문자열의 정규식을 활용하여 풀면 더 짧게 시간이 소요된다.

class Solution{
    static StringBuilder answer;
    public static String solution(String new_id){
        answer = new StringBuilder();
        answer.append(new_id.toLowerCase());
        version2();
        v3();v4();v5();v6();v7();
        return answer.toString();
    }
    public static void version2(){
        for (int i = 0; i < answer.length(); i++) {
            char tmp = answer.charAt(i);
            if((tmp <'0' || tmp >'9') && (tmp <'a'|| tmp >'z')){
                if (tmp != '-' && tmp !='_' && tmp !='.'){
                    answer.deleteCharAt(i--);
                }
            }
        }
    }
    public static void v3(){
        while(answer.indexOf("..")!=-1){
            int start = answer.indexOf("..");
                answer.replace(start,start+2,".");
        }
    }
    public static void v4(){
        if(answer.charAt(0) == '.')
            answer.deleteCharAt(0);
        if(answer.length()>0 && answer.charAt(answer.length()-1)== '.')
            answer.deleteCharAt(answer.length()-1);
    }
    public static void v5(){
        if(answer.length() == 0)
            answer.append("a");
    }
    public static void v6(){
        if (answer.length() >= 16)
            answer.delete(15,answer.length());
        v4();
    }
    public static void v7(){
        while(answer.length() < 3){
            answer.append(answer.charAt(answer.length()-1));
        }
    }
}
728x90

'알고리즘 > 프로그래머스' 카테고리의 다른 글

프로그래머스 메뉴 리뉴얼 - Java  (0) 2021.02.01
728x90

Obj. 자바의 멀티쓰레드 프로그래밍에 대해 학습.

Todo.

10-1. Thread 클래스와 Runnable 인터페이스

10-2. 쓰레드의 상태

10-3. 쓰레드의 우선순위

10-4. Main 쓰레드

10-5. 동기화

10-6. 데드락


10-0. Threa vs Process

프로세스와 스레드의 차이

 

프로세스란 ? 단순히 실행중인 프로그램(program)이라고 할 수 있다.

즉, 사용자가 작성한 프로그램이 운영체제에 의해 메모리 공간을 할당받아 실행 중 인것을 말한다.

이러한 프로세스는 프로그램에 사용되는 데이터와 메모리 등의 자원 그리고 스레드로 구성이 된다.

 

쓰레드란? 프로세스 내에서 실제로 작업을 수행하는 주체를 의미한다. 모든 프로세스에는 한 개 이상의 쓰레드가 존재하여 작업을 수행한다. 또한, 두개 이상의 쓰레드를 가지는 프로세스를 멀티쓰레드 프로세스 라고 한다.

 

10-1. Thread 클래스와 Runnable 인터페이스

- 쓰레드를 생성하는 방법은 크게 두 가지 방법이 있다.

1. Thread 클래스를 상속

2. Runnable 인터페이스를 구현

 

Thread 클래스 또한 Runnable 인터페이스를 구현 한 클래스이므로 어느 것이던 작업하고 싶은 내용을 run() 메소드에 작성을 하면 됨.

public static void runBasic() {
        Runnable runnable = new RunnableSample();
        new Thread(runnable).start();
        
        ThreadSample threadSample = new ThreadSample();
        threadSample.start();
        
        System.out.println("finish");

    }

public class RunnableSample implements Runnable {
    @Override
    public void run() {
        System.out.println("this is RunnableSample's run() method");
    }
}

public class ThreadSample extends Thread {
    @Override
    public void run() {
        System.out.println("this is ThreadSample's run() method.");
    }
}

여기서 메인에서 start()를 하는 것을 볼 수 있는데, run()을 하면 단지 메소드 호출의 의미를 가지므로 start()를 해야 호출 스택을 가지게 된다. 

 

언제 쓰는지 어떻게 구분 할까?

 - extends Thread, 즉 쓰레드를 상속받아 사용할 때 run()외에도 다른 것들을 Override를 해야할 필요가 있으면 Thread를 상속해서 만든다. run()만 사용해도 되는 경우에는 Runnable을 사용하면 된다. 또는 Thread를 상속받을 클래스가 다른 클래스도 상속받아야 된다면 Runnable을 사용한다.

 

10-2. 쓰레드의 상태

쓰레드의 상태는 크게 6가지로 구성된다.

NEW 쓰레드의 객체는 생성되었지만, 아직 시작되지 않은 상태
RUNNABLE 쓰레드가 실행 중인 상태
BLOCKED 쓰레드가 실행 중지 상태이며, 모니터 락(monitor lock)이 풀리기를 기다리는 상태
WAITING 쓰레드가 대기 중인 상태
TIME_WAITING 특정 시간만큼 쓰레드가 대기중인 상태
TERMINATED 쓰레드가 종료된 상태

쓰레드의 상태와 스케줄링에 관련된 메소드

1. sleep() - 주어진 시간 만큼 대기를 하게 된다. 또한 이를 사용할 때는 try-catch로 묵어 줘야한다. InterruptedExcepotion을 던질 수도 있기 떄문이다.

 

2. join() - 다른 쓰레드의 작업을 기다린다.  작업 중간에 다른 쓰레드의 작업을 참여 시킨다는 의미이므로 일정 시간 동안 작업을 수행하도록 한다. 별도의 파라메터가 없으면 쓰레드가 작업을 모두 마칠 때 까지 기다린다.

 

3. interrupted() - 쓰레드의 작업을 취소한다. 쓰레드에게 작업을 멈추라고 요청한다. 단지 요청을 할 뿐이지 쓰레드를 강제로 종료시키지는 못한다. 이는 인스턴스 변수를 바꾼다. 

 

4. yield() - 다른 쓰레드 에게 양보한다.

자신에게 주어진 실행 시간을 다른 차례의 쓰레드에게 양보한다. 그리고 자신은 실행 대기 상태가 된다.

 

5. stop(), suspend(), resume() - 쓰레드를 데드락으로 만들기 쉽기 때문에 deprecated 되었음.

 

10-3. 쓰레드의 우선순위

다중 작업을 진행할 때는 멀티쓰레드 방식을 사용하는 데  이 경우는 크게 동시성(Concurrency), 병렬성(Parallelism)으로 나뉜다. 

동시성은 싱글코어에 멀티 쓰레드를 번갈아 가면서 실행한다. 병렬성은 각 코어가 각 쓰레드를 실행한다.

 

각 쓰레드는 우선순위에 대한 필드를 가지고 있다. 

static int MAX_PRIORITY(최대 우선순위), static int MIN_PRIORITY(최소 우선순위), static int NORM_PRIORITY(기본 우선순위)가 있다. getPriority(), setPriority() 메소드를 통해서 쓰레드의 우선순위를 반환하거나 변경할 수 있다.

하지만, 이 우선순위는 절대적인 것이 아니다. -> 스케줄링 방식에 따라 지켜지지 않을 수 있다. 우선 순위로 많은 실행을 할 뿐이다. 

10-4. Main 쓰레드

자바 실행 환경인 JVM은 하나의 프로세스 이며, main()메소드가 main 쓰레드이다. 하나의 쓰레드만 사용 하는 어플리케이션을 싱글 쓰레드 어플리케이션이고, 여러개의 쓰레드가 돌아가면 멀티쓰레드가 되는 것이다. 이때 main 쓰레드가 종료되어도 멀티 쓰레드 환경에서는 프로게스가 종료되지 않는다.

 

Daemon 쓰레드 : main 쓰레드의 작업을 돋는 것이며 main 쓰레드가 종료되면 데몬 쓰레드는 강제적으로 종료됨. setDaemon(boolean)을 사용하여 설정한다.

 

10-5. 동기화

멀티 쓰레드의 경우에 자원을 공유 하게 되고 이를 critical section(임계 영역)이라고 한다. 여러 개의 쓰레드에서 한 개의 리소스를 사용하려고 할 때 사용하려는 쓰레드를 제외한 나머지들을 접근하지 못하게 막는 것이다.이를 Tread-Safe라고 한다. 자바에서는 Syncronized 를 사용해 왔는데 추가로 Atomic 클래스나  Volatile 키워드를 사용 할 수 있다.

 

Synchronized : 

자바의 예약어 중 하나로, 메소드 자체를 synchronized로 선언 하는 방법이 있고, 다른 하나는 메소드 내의 특정 블록만 Synchronized로 감싸는 방법이 있다.

 

class Table {
    String[] dishNames = {"donut", "donut", "burger"};
    final int MAX_FOOD = 6;
    private ArrayList<String> dishes = new ArrayList<>();

    public synchronized void add(String dish) {
        while (dishes.size() >= MAX_FOOD) {
            String name = Thread.currentThread().getName();
            System.out.println(name + " is waiting.");
            try {
                wait(); // COOK쓰레드를 기다리게 합니다.
                Thread.sleep(500);
            } catch (InterruptedException e) {
            }
        }
        dishes.add(dish);
        notify();  // 기다리고 있는 CUSTOMER를 깨우기 위함.
        System.out.println("Dishes:" + dishes.toString());
    }

    public void remove(String dishName) {
        synchronized (this) {
            String name = Thread.currentThread().getName();

            while (dishes.size() == 0) {
                System.out.println(name + " is waiting.");
                try {
                    wait(); // CUSTOMER 쓰레드를 기다리게 합니다.
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                }
            }

            while (true) {
                for (int i = 0; i < dishes.size(); i++) {
                    if (dishName.equals(dishes.get(i))) {
                        dishes.remove(i);
                        notify();  // 잠자고 있는 COOK 쓰레드를 깨우기 위함
                        return;
                    }
                } // for문의 끝

                try {
                    System.out.println(name + " is waiting.");
                    wait();
                    Thread.sleep(500);
                } catch (InterruptedException e) {

                }
            }
        }
    }

    public int dishNum() {
        return dishNames.length;
    }
}

10-6. 데드락

둘 이상의 쓰레드가 lock을 획득하기 위해 대기하는데, 이 lock을 잡고 있는 쓰레들도 똑같이 다른 lock을 기다리면서 서로  block상태에 놓이는 것을 말한다.

데드락은 다음 네가지 조건이 동시에 성립할 때 발생한다.

1. 상호 베제(Mutual Exclusion) - 자원은 한 번에 한 프로세스만 사용할 수 있어야 한다.

2. 점유 대기(Hold and wait) - 프로세스에 할당된 자원을 가진 상태에서 다른 자원을 기다린다.

3. 비선점(No Preemption) - 프로세스가 어떤 자원의 사용을 끝날 때 까지 그 자원을 뺏을 수 없다.

4. 순환 대기(Circular wait) - 각 프로세스는 순환적으로 다음 프로세스가 요구하는 자원을 가지고 있다.

 

해결하는 방법

- 예방, 회피, 무시

 

예방 - 상호배제 조건 제거, 점유와 대기 조건 제거, 비선점 조건 제거, 환형 대기 조건 제거 등이 있으나 비용이 많이 든다.

회피 - circular wait가 발생하지 않도록 자원 할당 상태를 검사한다, 자원 할당 그래프 알고리즘, 은행원 알고리즘 등이 있다.

무시 - 데드락 상황을 고려하는 것에 대한 비용이 낮다면 별다른 조치를 하지 않을 수 있다.

 

Reference

www.tcpschool.com/java/java_thread_concept

sujl95.tistory.com/63

yadon079.github.io/2021/java%20study%20halle/week-10

parkadd.tistory.com/48

728x90

'Java > [Whiteship]자바스터디' 카테고리의 다른 글

12주차 과제 : 애노테이션  (0) 2021.03.01
11주차 과제 : Enum  (0) 2021.02.28
9주차 과제 : 예외  (0) 2021.01.21
8주차 과제 : 인터페이스  (0) 2021.01.19
7주차 과제 : 패키지  (0) 2021.01.18
728x90

Obj. 자바의 예외에 대해 학습.

Todo.

9-1. 자바에서 예외 처리 방법 (try, catch, throw, throws, finally)

9-2. 자바가 제공하는 예외 계층 구조

9-3. Exception과 Error의 차이는?

9-4. RuntimeException과 RE가 아닌 것의 차이는?

9-5. 커스텀한 예외 만드는 방법


 

 

9-3. Exception과 Error의 차이는?

프로그램 실행 중 오작동하거나 비정상적으로 종료되는 경우에 이 원인에 따라 프로그램 에러 혹은 오류라고 한다.

발생 시점에 따라 컴파일 에러, 런타임 에러등으로 나눌 수 있다. 

 

오류(Error) : 시스템에 비정상적인 상황이 생김. try to catch를 하기 어려움.

예외(Exception) : 개발자가 구현한 로직에서 발생한 오류. try to catch 할 수 있음.

9-2. 자바가 제공하는 예외 계층 구조

Exception Hierachy

 

ㅅ출처 geeksforgeek

 

9-4. RuntimeException과 RE가 아닌 것의 차이는?

Checked Exception vs Unchecked Exception.

Checked는 컴파일 시점에서 확인 될 수 있는 예외이다. 이는 Exception Handler가 강제로 적용된다.

Unchecked는 컴파일 단계에서 확인 되지 않는 예외이며, 프로그래머가 알아서 처리를 해야한다.

 

9-1. 자바에서 예외 처리 방법 (try, catch, throw, throws, finally)

try-catch

예외 처리 하는 가장 기본적인 방법

try{

	// 예외가 발생할 수 있는 가능성이 있는 코드
    
    }catch(ExceptionType e1){
    
    	// 예외 발생 시 이를 처리하는 코드
        
    }finally{
    
    	// 생략 가능하다.
        // 예외가 발생해도 마지막에 실행이 됨.
  } 
    
        

try 블럭 안에 여러 catch 블록이 올 수 있으나, 해당 예외가 발생하면 더이상의 try의 순차적인 실행은 일어나지 않고, catch문을 실행 한 뒤 finally 문으로 진행한다.

 

Multi catch

Java 7버전 이후에는 하나의 catch 블록에서 다중 Exception Type을 지정할 수 있다. 사용은 " | "를 사용한다.

단 예외 클래스가 부모 자식관계에 있으면 

try{

	...
    }catch( Exception_A | Exception_B  e) {
    		...
    }
    	

try-with-resources

이전 try-finally에서 자바 라이브러리에서 사용되는 close메소들를 호출해서 닫아줘야 하는 자원이 많다. 이는 클라이언트가 놓치기 쉬워서 성능 저하를 유발할 수 있다. 이를 위해 finalizer를 사용 했지만 이는 Java 9에서 Deprecated 되었다. 자원을 회수하기 위할 때 사용한다.

try(BufferedReader br = new BufferedReader(new FileReader(path))){
		...
	}catch(IOException e){
    	...
    }
}

throw vs throws

throw 키워드를 통해서 고의로 예외를 발생 할 수 있다. 특정 예외를 만났을 때 더욱 구체적인 예외로 처리하고자 할 때에 사용한다. 사용 시점에 무조건 예외가 발생한다.

throws 키워드는 메서드를 정의할 때 사용하며, 메서드 내에서 예외를 처리하지 않고 자신을 호출한 상위 메서드에서 예외를 처리한다.

 

public class A{
	public static void main(String[] args){
    	Test test = new Test();
        
        try{
        	test.test("1","!");
            }catch(NumberFormatException e){
            	System.out.parinln("1");
                }
         }
    }
}

class Test{
	public void test(String a, String b) throws NumberFormatException{
    	try{
        	int sum = Integer.parsInt(a) + Integer.parsInt(b);
            System.out.parinln("2");
         }catch(NumberFormatException e){
         	System.out.parinln("3");
            throw e;
         }
     }
}

/*--------------------------------------
출력 : 
3
1*/
       
           

위와 같이 throw는 직접 예외를 날리는 것이다. 위는 throw 와 throws를 동시에 사용 한 것이며, 아래는 throws 만 사용 하는 경우이다.

public class A{
	public static void main(String[] args){
    	Test test = new Test();
        
        try{
        	test.test("1","!");
            }catch(NumberFormatException e){
            	System.out.parinln("1");
                }
         }
    }
}

class Test{
	public void test(String a, String b) throws NumberFormatException{

        	int sum = Integer.parsInt(a) + Integer.parsInt(b);
            System.out.parinln("2");
       
     }
}

/*--------------------------------------
출력 : 
1
*/
       
           

테스트 메서드에서 예외가 발생 했으나 throws로 호출한 메서드로 넘어가서 A의 메인에서 catch를 했다.

 

9-5. 커스텀한 예외 만드는 방법

java platform에서 자신만의 예외 클래스를 만들 수 있다.

1. 자바에서 표현되지 않는 타입의 예외가 필요할 때.

2. 다른 벤더가 작성한 클래스에서 제공한 예외 사항과 차별화 할 수 있다면?

3. 코드가 하나 이상의 관련 예외를 발생할때.

4. 다른 사용자의 예외를 사용할 때 해당 예외에 대한 액세스 권한이 사용자에게 부여되는가?

에 대해 조건이 부합된다면 예외 클래스를 만들어서 사용한다.

Custom Checked Exception

public class IncorrectFileNameException extends Exception {
    public IncorrectFileNameException(String errorMessage) {
        super(errorMessage);
    }

    public IncorrectFileNameException(String errorMessage, Throwable err) {
    	super(errorMessage, err);
    }
}

---------------------------------------------------------------------------------

try (Scanner file = new Scanner(new File(fileName))) {
    if (file.hasNextLine()) {
        return file.nextLine();
   	 }
	} catch (FileNotFoundException e) {
    if (!isCorrectFileName(fileName)) {
        throw new IncorrectFileNameException(
          "filename is incorrect : " + fileName , e);
    }
    // ...
}

Custom Unchecked Exception

public class IncorrectFileExtensionException
  extends RuntimeException {
    public IncorrectFileExtensionException(String errorMessage, Throwable e) {
        super(errorMessage, e);
    }
}

---------------------------------------------------------------------------------
try (Scanner file = new Scanner(new File(fileName))) {
    if (file.hasNextLine()) {
        return file.nextLine();
    }
} catch (FileNotFoundException e) {
    if (!isCorrectFileName(fileName)) {
        throw new IncorrectFileNameException(
          "filename is incorrect : " + fileName , e);
    }
    // ...
} catch (IncorrectFileExtensionException e) {
    if(!containsExtension(fileName)) {
        throw new IncorrectFileExtensionException(
          "Filename does not contain extension : " + fileName, e);
    }
    //...
}

 

Reference
www.geeksforgeeks.org/exceptions-in-java/?ref=lbp

www.notion.so/9-17a778bba6ed4436ac3d7b9415b6babb

bvc12.tistory.com/196

velog.io/@youngerjesus/%EC%9E%90%EB%B0%94-%EC%98%88%EC%99%B8-%EC%B2%98%EB%A6%AC

728x90

'Java > [Whiteship]자바스터디' 카테고리의 다른 글

11주차 과제 : Enum  (0) 2021.02.28
10주차 과제 : 멀티쓰레드 프로그래밍  (0) 2021.01.27
8주차 과제 : 인터페이스  (0) 2021.01.19
7주차 과제 : 패키지  (0) 2021.01.18
6주차 과제 : 상속  (0) 2021.01.17

+ Recent posts