21년 1월 27일

한 일

  • 자바 - 비동기 프로그래밍으로 커피를 판매하는 시뮬레이션을 구현해 보았다.(CompleteFuture를 사용했다.)

    • 구현에 필요한 클래스를 설계하고 객체간의 메세지를 보내(메소드 실행) 이벤트를 발생하게 했다.

    • 객체 각자가 비동기적으로 일을 수행해, 주문을 받은 커피를 만들고 커피가 완료됐다고 출력하는게 목표였다.

    • 만든 클래스는 다음과 같다.

      1. 주문을 받는 Cashier Class

      2. 주문 목록을 갖고있는 OrderList Class

      3. OrderList를 보고 일을 할당해주는 Manager Class

      4. 커피를 만드는 Barista Class

      5. 완료된 목록을 출력해주는 DashBoard Class

      6. 커피 종류인 CoffeeType Enum

      7. 커피 종류와 주문한 고객정보를 갖고있는 Coffee Class

      8. 주문한 고객정보와 Coffee를 모두 담고 있는 Order Class

        (고객1이 아메리카노2잔,카페라떼3잔을 시켰다면 커피1잔은 Coffee Class에 해당하고, 전체 주문 한건은 Order Class에 해당)

    • CompleteFuture에서 제공하는 runAsync나 supplyAsync를 사용하면 Executors로 직접 쓰레드풀을 생성할 필요가 없이,

      ForkJoinPool에서 제공하는 쓰레드 풀에 Task를 할당할 수 있다. (매우 편리하다!)

    • CompleteFuture를 사용하면 콜백지옥없이 thenApplyAsync와 같은 메소드를 통해, promise패턴으로 구현이 가능하다.

    • 모든 주문이 완료된 상태에서 3초간 input이 들어오지 않으면 종료시킨다는 조건이 있었는데, io 블락중인 상태를 어떻게 종료해야할지 몰라서 정말 힘들었다.

      1. io입력 받는 부분을 CompletFuture를 통해 non-block 상태로 실행시킨다.

      2. future.getNow(null) 메소드를 통해 (task가 완료되면 리턴값을, 아직 진행중이면 null을 반환한다는 의미)

        io로 input이 들어왔는지 판단한다.

      3. io로 input이 들어오지 않은 상태에서 모든 주문이 끝났고, 주문이 끝난지 3초 이상 지났으면 함수를 return해준다.

      4. 데몬 쓰레드에서 돌고있는 Scanner.nextLine()이 종료되지 않은 상태에서 메인 쓰레드가 종료되기 때문에, 프로세스가 종료된다.

        public void startOrder(){
                showMenu(); //메뉴 목록 출력
                showHowToOrder(); //주문하는 방법 출력
                orderCompleted = false; //주문받기 시작했기 때문에, 주문이 완료된적 없음
               
                Scanner sc = new Scanner(System.in);
                while(true) {
                    CompletableFuture<String> listen = CompletableFuture.supplyAsync(() -> sc.nextLine());
                    String orderString;
                    while((orderString = listen.getNow(null)) == null){ //listen값이 null이 아닌동안 계속 확인
                        try{Thread.sleep(10);} catch(InterruptedException e) {};
                        double currentTime = System.currentTimeMillis();
                        if(orderCompleted && currentTime - completedTime >= 3000){ //주문완료, 3초 지났으면 종료
                            System.out.println("모든 메뉴가 완성되었습니다.");
                            return;
                        }
                    }
                    orderCompleted = false;
                    Order order = translateOrder(orderString);
                    if(order == null){
                        System.out.println("올바른 형식을 입력해주세요.");
                    } else {
                        orderList.addOrder(order);
                    }
                }
            }
        

잘못한 것

  • 구현이 생각보다 어려워서, 알고리즘 공부와 자바의정석 읽기를 못했다.

잘한 것

  • 생각보다 어려웠는데 새벽 3시까지 코딩해서 결국 다 만들었다 ㅎㅎ

느낌

  • 힘든 일이 있어서 멘붕이 왔었는데, 다시 회복하고 있다.
  • 깨졌던 공부 루틴을 회복하기 시작해서 좋다.
  • CompleteFuture를 사용하니까 너무 편리하다. (내부 작동원리 등은 계속 써가면서 공부해야 할 것 같다.)

할 일

  • 코드스쿼드 미션 하기
  • 프로그래머스 문제 풀기