[TIL] 1월 25일

yeon·2021년 1월 25일
0

동기와 비동기 개념

아래 블로그 참조

동기와 비동기의 개념과 차이

동기(Synchronous)는 정확히 무엇을 의미하는걸까?

동기와 비동기, 그리고 블럭과 넌블럭

  • 동기

    • 바로 요청을 하면 시간이 얼마가 걸리던지 그 자리에서 결과가 주어져야 함
    • A노드와 B노드 사이의 작업 처리 단위(transaction)을 동시에 맞추겠다.
    • 설계가 간단하고 직관적이지만 결과가 주어질 때까지 다른 것을 하지 못하고 대기해야함
  • 비동기

    • 서로의 행위, 목적이 다르기때문에 둘의 작업처리시간은 일치하지 않고, 일치하지 않아도 된다.
    • 요청한 그 자리에서 결과가 주어지지 않음
    • 노드 사이의 작업 처리 단위를 동시에 맞추지 않아도 됨
    • 설계가 복잡하지만 결과가 주어지는데 시간이 걸리더라도 그 시간동안 다른 일을 할 수 있다. 자원을 효율적으로 사용 가능
  • 동기와 비동기는 프로세스의 수행 순서 보장에 대한 매커니즘

    • 동기는 추구하는 같은 행위 또는 목적이 동시에 이루어지고, 비동기는 추구하는 행위나 목적이 다를 수 도 있고, 동시에 이루어지지도 않는다.
  • blocking과 non-blocking은 프로세스의 유휴 상태에 대한 개념

  • 시험날의 학생과 선생 (비동기의 예시)

    • blocking과 non-blocking의 차이
    • 학생이 시험지를 건내고 선생님이 채점을 끝내고 시험지를 돌려받기를 기다리기만 한다면 학생을 블록상태
    • 선생님이 채점이 완료되었다는 전송을 받기 전까지 다른 것을 하게 되면 학생의 상태는 논블록 상태

자바의 정석 11장 학습

ArrayList

Vector나 ArrayList같이 배열을 이용한 자료구조는 용량을 변경할 때 새로운 배열을 생성하고, 기존의 배열로부터 새로 생성된 배열로 데이터를 복사해야돼서 효율이 떨어진다.

데이터를 읽어오고 저장하는데는 효율이 좋다.

처음에 인스턴스 생성시, 저자할 데이터의 개수를 잘 생각해서 충분한 용량의 인스턴스를 생성한다.

  • 예제2 (587p)
  • 긴 문자열의 데이터를 원하는 길이로 잘라서 ArrayList에 담는 코드
public class ArrayListEx2 {
    public static void main(String[] args) {
        final int LIMIT = 10;   // 자르고자 하는 글자의 개수
        String soure = "0123456789abcdefghijABCDEFGHIJ!@#$%^&*()ZZZ";
        int lenght = soure.length();

        List list = new ArrayList(lenght/LIMIT + 10);   // 크기를 여유있게 잡는다.

        for(int i =0; i < lenght; i+=LIMIT){
            if(i+LIMIT < lenght)
                list.add(soure.substring(i,i+LIMIT));
            else
                list.add(soure.substring(i));
        }

        for(int i = 0; i <list.size(); i++){
            System.out.println(list.get(i));
        }
    }
}
  • substring()에 인자가 하나만 들어가면 그 인덱스이후의 문자열을 리턴하는 것

  • Vector 예제(588p)

public class VectorEx1 {
    public static void main(String[] args) {
        Vector v = new Vector(5);
        v.add("1");
        v.add("2");
        v.add("3");
        print(v);

        // 빈 공간을 없앤다. 
        v.trimToSize();
        System.out.println("=== After trimToSize() ===");
        print(v);

        v.ensureCapacity(6);
        System.out.println("=== After ensureCapacity ===");
        print(v);

        v.setSize(7);
        System.out.println("=== After setSize ===");
        print(v);

				v.clear();
        System.out.println("=== After clear ===");
        print(v);
    }
    public static void print(Vector v){
        System.out.println(v);
        System.out.println("size : " + v.size());
        System.out.println("capacity : " + v.capacity() );
    }
}

</> 실행 결과

[1, 2, 3]
size : 3
capacity : 5
=== After trimToSize() ===
[1, 2, 3]
size : 3
capacity : 3
=== After ensureCapacity ===
[1, 2, 3]
size : 3
capacity : 6
=== After setSize ===
[1, 2, 3, null, null, null, null]
size : 7
capacity : 12
=== After clear ===
[]
size : 0
capacity : 12
  • Vector v = new Vector(5);
    • capacity가 5인 v 생성
  • v.trimToSize();
    • trim : 다듬다, 잘라내다.
    • v의 빈 공간을 없애서 size와 capacity를 갖게한다.
    • 배열은 크기를 변경할 수 없어서 새로운 배열을 생성해서 그 주소값을 변수 v에 할당한다.
    • 기존의 Vector 인스턴스는 가비지컬렉터에 의해서 메모리에서 제거된다.
  • v.ensureCapacity(6);
    • v의 capacity가 최소한 6이 되게 한다.
    • 만약 v의 capacity가 6이라면 아무일도 일어나지 않는다.
    • 이 경우에는 v의 capacity가 3이므로 크기가 6인 배열을 생성해서 v의 내용을 복사한다.
    • 새로운 인스턴스를 생성하게 되는 것
  • v.setSize(7);
    • v의 size가 7이 되도록 한다.
    • capacity가 충분하다면 새로운 인스턴스를 생성하지 않는다.
    • 이 경우에는 capacity가 6이여서 새로운 인스턴스를 생성해야한다.
    • Vector는 capacity가 부족할 경우 자동적으로 기존의 크기보다 2배로 증가한다.
    • 따라서 v의 capacity는 12가 된다.

LinkedList

배열의 단점을 보완한 자료구조이다.

불연속적으로 존재하는 데이터를 서로 연결한 형태

이동 방향이 단방향이기 때문에 다음 요소의 접근은 쉽지만, 이전 요소의 접근은 어렵다. → 이를 보완한것이 더블 링크드 리스트

  • 배열의 장점

    배열은 연속적인 특성을 가지고 있음

    • 구조가 간단하다.
    • 데이터를 읽는데 걸리는 시간(접근시간, access time)이 가장 빠르다.
  • 배열의 단점

    • 크기를 변경할 수 없다.

      → 새로운 배열을 생성해서 데이터를 복사해야 한다.

      → 크기의 변경을 피하기 위해 여유로운 크기의 배열을 생성하면 메모리가 낭비된다.

    • 중간에 데이터를 추가하거나 삭제할 때 시간이 많이 거린다.

      • 데이터들을 이동해야하므로
      • 하지만 순차적인 데이터의 추가나 삭제 (끝에 추가하고 삭제)는 빠르다.
  • 링크드 리스트의 장점

    • 데이터의 추가와 삭제가 빠르다.
  • 링크드 리스트의 단점

    • 데이터 접근성이 나쁘다.

더블 링크드 리스트(이중 연결 리스트, doubly linked list)

  • 접근성 향상
  • 다음 요소뿐만 아니라 이전 요소 참조 가능

더블 써큘러 링크드 리스트(이중 원형 연결리스트, doubly circular linked list)

  • 더블 리스트의 첫번째 요소와 마지막 요소를 연결시킨 것
  • TV의 마지막 채널에서 다음 채널로 이동하면 처음 채널로 이동하는 개념

ArrayList vs LinkedList?(601p)

  1. 요소의 끝에 추가/삭제 하는 경우는 ArrayList가 LinkedList보다 빠르다.
  2. 중간에 데이터를 추가/삭제 하는 경우는 LinkedList가 ArrayList보다 빠르다.

Stack과 Queue

Stack

  • LIFO(Last In First Out)
  • 저장 push, 추출 pop
  • 순차적으로 데이터를 추가하고 삭제하기 때문에 ArrayList와 같은 배열 기반의 컬렉션클래스가 적합
  • Stack 클래스 있음

Queue

  • FIFO(First In First Out)
  • 저장 offer, 추출 poll
  • 데이터의 추가와 삭제가 용이한 LinkedList로 구현하는 것이 적합
    • Queue는 데이터를 꺼낼 때, 맨 처음 요소를 삭제하므로 배열 기반 자료구조는 비적합
  • Queue는 인터페이스(클래스 없어서 Queue를 구현한 클래스를 써야함)

Stack의 메서드(604p)

  • boolean empty()

  • 추출

    • Object peek()

      : 맨위에 있는 객체를 보기만 하고, 꺼내지는 않는다.

    • Object pop()

      : 맨위에 저장된 객체를 꺼낸다.

  • 추가

    • Object push(Object item)
  • 위치 찾기

    • int search(Object o)

      : 위치 반환, 배열과 달리 0이 아닌 1부터 시작, 배열의 indexOf 와 비슷한 메서드

Queue의 메서드(605p)

  • 추가

    • boolean add(Objcet o)

      : 저장공간이 부족하면 예외 발생

    • boolean offer(Object o)

      : 예외 발생하지 않음

  • 추출과 삭제

    • Object poll()

      : 객체를 꺼내서 반환, 비어있으면 null 반환

    • Object peek()

      : 삭제 없이 요소를 읽어온다, 비어있으면 null 반환

    • Object remove()

      : 객체를 꺼내서 반환, 비어있을 시 예외 발생

Stack과 Queue 예제

public class StackQueueExam {
    public static void main(String[] args) {
        Stack st = new Stack();
        Queue q = new LinkedList();

        st.push("0");
        st.push("1");
        st.push("2");

        q.offer("0");
        q.offer("1");
        q.offer("2");

        System.out.println("== Stack ==");
        while(!st.empty()){
            System.out.println(st.pop());
        }
        System.out.println("== Queue ==");
        while ((!q.isEmpty())){
            System.out.println(q.poll());
        }
    }
}

Stack과 Queue의 활용

스택활용 예 - 수식계산, 수식괄호검사, undo/redo, 웹브라우저의 뒤로/앞으로

큐의 활용 예 - 최근 사용문서, 작업 대기목록, 버퍼(buffer)

  • 예제 - 최근 5개의 명령어 이력 history
public class QueueEx1 {
    static Queue q = new LinkedList<>();
    static final int MAX_SIZE = 5;  // Queue에 최대 5개까지만 저장되도록

    public static void main(String[] args) {
        System.out.println("help를 입력하면 도움말을 볼 수 있습니다.");

        while (true) {
            System.out.print(">> ");
            Scanner s = new Scanner(System.in);
            String input = s.nextLine().trim();

            if ("".equals(input)) continue;

            if (input.equalsIgnoreCase("q")) {
                System.exit(0);
            } else if (input.equalsIgnoreCase("help")) {
                System.out.println(" help - 도움말을 보여줍니다.");
                System.out.println(" q - 프로그램을 종료합니다.");
                System.out.println(" history - 최근에 입력한 명령어를 " + MAX_SIZE + "개 보여줍니다.");
            } else if(input.equalsIgnoreCase("history")){
                int i = 0;  
                // 입력받은 명령어 저장
                save(input);

                LinkedList tmp = (LinkedList) q;
                ListIterator it = tmp.listIterator();

                while (it.hasNext())
                    System.out.println(++i +"." +it.next());
            } else {
                save(input);
                System.out.println(input);
            }
        }
    }

    public static void save(String input){
        // queue에 저장
        if(!"".equals(input))
            q.offer(input);

        // queue의 최대 크기를 넘으면 제일 처음 요소 삭제
        if(q.size() > MAX_SIZE)
            q.remove();
    }
}
  • String input = s.nextLine().trim();
    • trim() : 입력받은 라인의 앞뒤 공백을 삭제한다. (중간의 공백은 그대로)
  • if( !"".equals(input) );
    • ! input.equals("") 와 동일 하지만 이 경우에는 input ! = null && ! input.equals("")라고 해주어야 nullPointerException이 발생하지 않는다.

오늘 한 일

  • 동기, 비동기, blockint, non-blocking 개념에 대해 명확히 설명할 수 있을 정도로 이해하지 못했고 예시의 경우와 대략적인 느낌만 알거 같다.
  • 자바의 정석 11장 컬렉션 프레임웍
    • ArrayList와 Vector의 장단점? Vector의 사용, ArrayList와 LinkedList의 비교, LinkedList의 종류, Stack과 Queue의 특징, 메서드
  • 너무 피곤해서 저녁먹고 자다 일어나서 공부했는데 정신이 계속 멍했다. 자더라도 책상에서 쪽잠을 자는편이 나은것 같다.

Todo

  • 이번주까지 자바의 정석 11장 끝내기
  • 한달동안 자바의 정석 완독하기

0개의 댓글