JAVA/Effective Java 90

[아이템 80] 쓰레드보다는 실행자, 태스크, 스트림을 애용하라

실행자 프레임워크(Executor Framework) java.util.concurrent 패키지는 실행자 프레임워크(Executor Framework)라고 하는 인터페이스 기반의 유연한 태스크 실행 기능을 담고 있습니다. 과거에는 단순한 작업 큐(work queue)를 만들기 위해 수많은 코드를 작성했어야 했지만, 이제는 다음과 같이 간단하게 작업 큐를 생성할 수 있습니다. 1. 실행자 서비스(ExecutorService) 주요 기능 코드 부연 설명 get 메서드: 특정 태스크가 완료되기를 기다림 invokeAny 메서드: 태스크 모음 중 아무것 하나가 완료되기를 기다림 invokeAll 메서드: 모든 태스크가 완료되기를 기다림 awaitTermination 메서드: 실행자 서비스가 종료하기를 기다림 ..

JAVA/Effective Java 2024.04.07

[아이템 79] 과도한 동기화는 피하라

과도한 동기화는 다음과 같은 부작용을 초래합니다. 성능을 떨어뜨리고 Deadlock 상태에 빠드리고 심지어 예측할 수 없는 동작을 낳을 수 있음 응답 불가와 안전 실패를 피하려면 동기화 메서드나 동기화 블록 내 제어를 절대로 클라이언트에 양도하면 안 됩니다. 동기화된 클래스 관점에서, 다음과 같은 메서드들은 "외계인 메서드(alien method)"로 알려져 있는데, 이는 이러한 메서드들이 어떤 동작을 수행할지 확신할 수 없으며, 예외를 발생시키거나, 데드락 상태에 빠뜨리거나, 데이터를 손상시킬 수 있기 때문입니다. 동기화된 코드 블록 내 재정의 가능한 메서드 클라이언트가 전달한 함수 객체 외계인 메서드(Alien Method) 코드 부연 설명 관찰자들은 addObserver()와 removeObserv..

JAVA/Effective Java 2024.04.07

[아이템 78] 공유 중인 가변 데이터는 동기화해 사용하라

동기화 동기화란 멀티 쓰레드 환경에서 하나의 메서드 혹은 블록을 한 번에 하나의 쓰레드만 수행하도록 보장하는 것을 의미합니다. 싱글 쓰레드 환경에서는 동기화 걱정 안 해도 됨 멀티 쓰레드 환경에서는 여러 개의 쓰레드가 하나의 객체를 공유해서 사용하는 경우가 있으므로 동기화 처리 필요 1. 동기화 과정 한 객체가 일관된 상태를 가지고 생성되었을 때 해당 객체에 접근하는 메서드는 다른 쓰레드가 메서드를 실행할 수 없도록 락을 검 락을 건 메서드는 객체의 상태를 확인하거나 필요하면 수정 정리하자면 일관된 하나의 상태에서 다른 일관된 상태로 변화시킴 메서드 실행이 끝나면 락을 해제 2. 동기화 특징 동기화를 제대로 사용할 경우 어떤 메서드도 해당 객체의 상태가 일과되지 않은 순간을 목격할 수 없음 동기화가 없을..

JAVA/Effective Java 2024.03.29

[아이템 77] 예외를 무시하지 말라

API 설계자가 메서드 선언에 예외를 명시하는 이유는 적절한 조치가 필요하기 때문인데 많은 개발자들이 API 설계자의 목소리를 흘려버리고 있습니다. 아래 코드처럼 try문으로 감싼 뒤 catch 블록에서 아무 일도 하지 않는 코드들이 많음 코드 문제점 예외는 문제 상황에 잘 대처하기 위해 존재하는데 catch 블록을 비워두면 예외가 존재할 이유가 없어짐 운이 좋아 코드가 잘 돌아갈 수도 있지만, 적절한 예외 처리가 이루어지지 않으면 오동작할 가능성이 높아짐 따라서 빈 catch 블록은 절대적으로 피해야 함 예측할 수 있는 예외 상황이든 프로그래밍 오류든, 빈 catch 블록으로 못 본 척 지나치면 해당 프로그램은 오류를 내재한 채 동작 그러다 어느 순간 문제의 원인과 아무 상관없는 곳에서 갑자기 죽어버릴..

JAVA/Effective Java 2024.03.29

[아이템 76] 가능한 한 실패 원자적으로 만들라

실패 원자성 호출된 메서드가 예외 발생으로 인해 실패하더라도 객체가 메서드 호출 전 상태를 유지하는 특성 실패 원자성이 보장되면 Checked Exception을 던졌을 때 호출자가 오류 상태를 복구할 수 있으므로 유용함 메서드를 실패 원자적으로 만드는 방법은 총 네 가지가 있으며 다음과 같습니다. 불변 객체로 설계 매개변수 유효성 검사 복사본에 로직을 수행 후, 성공적으로 수행이 완료될 경우에만 원본 객체와 Swap 작업 도중의 에러를 가로채는 복구 코드를 작성하여 롤백 1. 불변 객체로 설계 불변 객체는 생성 시점에 고정되어 절대 변하지 않기 때문에 태생적으로 실패 원자적 메서드가 실패하면 새로운 객체가 생성되지 않을 수 있으나 기존 객체가 불안정한 상태에 빠지는 일은 없음 2. 매개변수 유효성 검사..

JAVA/Effective Java 2024.03.29

[아이템 75] 예외의 상세 메시지에 실패 관련 정보를 담으라

예외를 잡지 못해 프로그램이 실패하면 자바 시스템은 아래와 같이 해당 예외의 stack trace 정보를 자동으로 출력합니다. 예상하지 못한 장애가 발생했을 때 위와 같은 정보가 실패 원인을 분석해야 하는 개발자 혹은 SRE가 얻을 수 있는 유일한 정보인 경우가 많습니다. 특히 재현하기 어려운 장애일 경우 더 자세한 정보를 얻기가 어렵거나 불가능하기 때문에 예외의 toString() 메서드에 실패 원인에 관한 정보를 가능한 많이 담아 반환해야 합니다. 예외 메시지 관련 원칙 실패 순간을 포착하려면 발생한 예외와 관련된 모든 매개변수와 필드의 값을 실패 메시지에 담아야 함 stack trace에는 예외가 발생한 파일명과 예외가 발생한 line이 출력되는 것이 일반적이므로 문서와 소스코드를 통해 얻을 수 있..

JAVA/Effective Java 2024.03.29

[아이템 74] 메서드가 던지는 모든 예외를 문서화하라

메서드가 발생시키는 예외는 해당 메서드를 올바르게 사용하는 데 매우 중요한 정보이므로 각 메서드가 발생시키는 예외를 하나씩 문서화하는 것이 필요합니다. Checked Exception은 항상 별도로 선언하고, 각 예외가 발생하는 상황을 JavaDoc의 @throws 태그로 문서화하라 공통 상위 예외 클래스 하나로 뭉뚱그려 선언하는 일은 지양해야 함 메서드 사용자에게 각 예외에 대처할 수 있는 힌트를 주지 못할 뿐만 아니라 같은 맥락에서 발생할 여지가 있는 다른 예외들까지 삼켜버릴 수 있어 API 사용성을 떨어뜨림 ex) Exception이나 Throwable을 throw 한다고 선언해서는 안됨 예외 케이스: main 메서드는 JVM만이 호출하므로 Exception으로 묶어서 던지도록 선언해도 괜찮음 1...

JAVA/Effective Java 2024.03.28

[아이템 73] 추상화 수준에 맞는 예외를 던지라

로그를 확인하는 도중 일을 수행하는 도중 예상치 못한 예외가 발생하면 상당히 당황스러울 수 있습니다. 이는 메서드가 저수준 예외를 처리하지 않고 상위 레이어로 던질 때 종종 발생하며 다음과 같은 문제가 발생할 수 있습니다.. 내부 구현 방식을 상위 layer에 드러내 윗 레벨 API를 오염시킬 수 있으며 다음 릴리즈에서 구현 방식이 변경될 경우 다른 예외가 발생해 기존 클라이언트 프로그램을 깨지게 할 수 있음 이번 아이템에서는 위 문제를 방지하기 위한 기법들을 소개합니다. 1. 상위 메서드에서 저수준 예외를 번역하자 상위 메서드에서는 저수준 예외를 잡아 자신의 추상화 수준에 맞는 예외로 바꿔 던져야하며 이를 `예외 번역(Exception Translation)`이라고 함 ex) 데이터베이스 연결을 시도할..

JAVA/Effective Java 2024.03.27

[아이템 72] 표준 예외를 사용하라

객체 지향 프로그래밍의 장점으로 `재사용성`이라는 특성은 항상 강조되며, 이는 예외도 마찬가지입니다. 자바 라이브러리는 대부분 API에서 쓰기 충분한 수의 예외를 제공 표준 예외를 재사용해라 표준 예외는 많은 개발자들에게 이미 익숙하고 널리 사용되기 때문에 적용 시 다른 사람들이 API를 익히고 사용하기 쉽습니다. 또한, 예외 클래스 수가 적을수록 메모리 사용량도 줄고 클래스를 적재하는 시간도 적게 걸린다는 장점이 존재합니다. 달리 말하자면 무분별하게 Custom Exception을 생성하면 빌드하는 시간도 오래 걸리고 클래스 로딩 시간이 오래 걸린다는 뜻입니다. 그러나 대부분의 상용 서비스의 API 규격서에는 예외 상황이 발생하더라도 단순히 예외를 던지는 것이 아닌 API 응답을 반환하고, 이들은 대부..

JAVA/Effective Java 2024.03.25

[아이템 71] 필요 없는 검사 예외 사용은 피하라

아이템 70에서 Checked Exception과 Unchecked Exception에 대해 다루었습니다. Checked Exception은 try-catch 블록으로 감싸거나 예외를 던지는 행위를 강제하기 때문에 싫어하는 자바 개발자가 많지만 제대로 활용할 경우 API와 프로그램의 질을 높일 수 있습니다. Checked Exception은 다음과 같은 상황에서 적절하며, 이에 해당하지 않는 경우에는 Unchecked Exception을 사용하는 것이 적절합니다. API를 제대로 사용해도 발생할 수 있는 예외 프로그래머가 의미 있는 조치를 취할 수 있는 경우 요약하면, Checked Exception은 특정한 상황에서만 사용하는 것이 좋으며, 일반적으로는 Unchecked Exception을 선호합니다...

JAVA/Effective Java 2024.03.25