본문 바로가기
📝 회고/✅ 22년 회고

[일일 회고] 22.01.24~25 - 자바의 동시성 프로그래밍과 몇 개의 아이템 적용

by kukim 2022. 1. 25.

📚개발 일지

어제, 오늘은 자바로 멀티 프로세스와 스레드 스케줄링을 공부하고 간단하게 구현했다.  저번 주 프로젝트에선 탑다운, 설계에 많은 시간을 두었다. 하지만 너무 큰 범위로 설계해서 실제로 작게 쪼개 구현하는 일이 어려웠다. 이번 프로젝트는 설계를 대략적으로 잡고 바텀엄 방식으로 바닥부터 작은것 하나씩 구현했다. 구현하면서 처음 설계했던 부분을 보충하는 식이었다. 작게 구현하다 보니 구현체에 자신감이 생기고 즐거움이 있었다.

 

프로젝트에 적용한 아이템(?)은 다음과 같다.

 

✅ toString() 재정의 + StringBuilder 를 활용한 주요 정보 반환

2022.01.15 - 모든 구현 클래스에서 Object의 toString 재정의를 고려하자 🗣 에 정리했던 item12를 적용했다. 

매번 객체의 정보를 사용하기 위해 바깥에서 정보가 필요한 객체의 getter를 사용했었지만 이번 기회로 한 번에 객체 정보를 사용했다.

@Override
public String toString() {
    StringBuilder b = new StringBuilder();
    for (Process process : processes) {
        b.append(process.toString());
    }
    return b.toString();
}

 

✅ static를 사용한 정수형 매크로상수가 아닌 enum 클래스 적용

2022.01.21 - [☕️ JAVA] - 자바의 'enum'과 'lambda'를 클래스로 이해해보기 🔎 item34를 적용했다. 이전 코드는 static 멤버 변수로 하드 코딩을 피했지만 이번엔 enum을 적용했다. 가독성뿐만 아니라 타입을 방어할 수 있었다.

public enum Status {
    READY,
    RUNNING,
    WAITING,
    TERMINATED,
}


// 비교 시 사용
while (osStatus != Status.TERMINATED) {

}

 

✅ 자바의 동시성 프로그래밍 : 동기화

2022.01.24 - 자바의 동시성 프로그래밍, 가변 데이터를 동기화하는 3가지 방법(+a. 자바 기본 타입의 원자성에 대하여) 글을 작성했고 이를 프로젝트에 적용했다. 3가지 방법 중 배타적 실행을 지원하는 synchronized와 Atomic class를 적용하여 가변 데이터 동기화를 했다.

// synchronized
public synchronized void work() {
    if (this.workTime < this.processEndTime) {
        this.workTime += 1;
    }
}

// Atomic class
private AtomicInteger atomicWorkTime;

public void work() {
    if (this.atomicWorkTime.get() < this.processEndTime) {
        this.atomicWorkTime.incrementAndGet();
    }
}

 

✅ 자바의 동시성 프로그래밍 : 스레드 생성

스레드 생성하는 문법적인 차이의 발전이 있었다. 스레드 생성은 new Thread()와 Runnable으로 했다. 초기 Thread() 안에 들어가는 매개 변수를 따로 객체로 만들었다. 

    private void startThread() {
        Thread[] th = new Thread[threadSize];
        for (int i = 0; i < threadSize; i++) {
            th[i] = new Thread(new Worker(this));
            th[i].start();
        }
        // 중략
    }

    public class Worker implements Runnable {
        private Process process;
    
        public Worker(Process process) {
            this.process = process;
        }
    
        @Override
        public void run() {
            process.work();
        }
    }

하지만 Runnable는 함수형 인터페이스 이기 때문에 람다로 표시가 가능하다. 위에서 생성했던 Worker 객체를 삭제하고 람다로 변경했다. 또한 람다식을 메서드 참조로 간단히 표현했다.

@FunctionalInterface
public interface Runnable {
    public abstract void run();
}

// 람다식 사용 X
th[i] = new Thread(new Worker(this));

// 람다식 사용 O
th[i] = new Thread(() -> { work(); });

// 람다식 -> 매서드 참조
th[i] = new Thread(this::work);

 

고민

🧐 바텀업 방식으로 개발하니 탑다운 방식보다 개발이 쉬웠다. 또한 이 방식이 전체 설계에 도움을 준다고 느끼면서도 전체적인 설계 없이는 올바른 방향으로 갈 수 있을까? 하는 고민도 있다. 탑다운과 바텀업의 조화는 어떻게 이뤄야 할까?

🧐 구현을 마치고 되돌아보니 OOP나 변수명 등 리팩터링할 부분이 많이 보였다. 아직 익숙하지 않다. 차근차근해봐야겠다.

🧐 어제오늘 프로젝트에 대해 동료들의 도움 요청에 설명을 해주었다. 나 또한 동료의 코드를 보며 여러 정답들을 보았다. 건강한 지식 전달은 무엇일까? 바로 정답을 말해주는 것이 좋을까? 내가 알고 있는 정답은 수많은 정답 중 하나이기에 생각이 갇히진 않을까 걱정이 든다. 도움을 주는 사람과 받는 사람 모두 윈윈 할 수 있는 피드백은 무엇일까? 


👍 Keep

건강한 루틴을 지켰다.(운동, 공부 중간 휴식, 환기)

큰 문제를 작은 문제로 바꾸어 해결했다.

학습한 내용을 문서화했다.

🔥Problem

카페인 과다 복용 (한 잔만 마셔도 잠을 못 자는 편인데 세 잔이나...)

작은 문제로만 풀다 보니 큰 문제에 접근하지 못했다.

알고 있다는 착각

하나에만 집중했다.

🚒 Try

1일 1커피

해결해야 할 문제를 큰 문제와 작은 문제로 번갈아가며 생각하기

알고 있다고 생각하는 것을 되돌아보자. 이거 정말 내가 알고 있는 건가? 5살 아이에게 설명한다고 가정하고 혼잣말이라도 하며 점검해보자

한 가지 주제에만 신경 쓰니 일률이 떨어진다. 코딩이나 학습에도 콘텍스트 스위칭을 적용해보자.

댓글