wait와 notify wait와 notify는 올바르게 사용하기가 아주 까다로우니, java.util.concurrent의 고수준 동시성 유틸리티를 사용하자. ▶ wait(), notify(), notifyAll() 포스팅 바로가기 https://devfunny.tistory.com/855 wait()과 notify(), notifyAll() wait(), notify(), notifyAll() synchronized로 동기화해서 공유 데이터를 보호할때 특정 스레드가 객체의 락을 가진 상태로 오랜 시간을 보내지 않도록 하는것도 중요하다. 락을 오랜시간 보유하게되면, 다 devfunny.tistory.com 1) 실행자 프레임워크 https://devfunny.tistory.com/807?category..
들어가기전 아이템 80에서 나오는 '실행자 프레임워크'에 대해 아래의 포스팅으로 공부하자. https://devfunny.tistory.com/807?category=957918 [JAVA8 병렬프로그래밍] Executors 클래스, ExecutorService 인터페이스 Executors 클래스 - Executor 인터페이스 : 컨커런트 API의 핵심 인터페이스다. 이 인터페이스를 구현한 여러 종류의 클래스를 기본으로 제공한다. - 스레드 풀 : 스레드를 관리하기 위한 풀이다. 병렬 devfunny.tistory.com java.util.concurrent 패키지의 등장 java.util.concurrent 패키지는 실행자 프레임워크(Executor Framework)라고 하는 인터페이스 기반의 유연한..
들어가기전 https://devfunny.tistory.com/669?category=895441 [교재 EffectiveJava] 아이템 78. 공유 중인 가변 데이터는 동기화해 사용하라 synchronized 키워드 해당 메서드나 블록을 한번에 한 스레드씩 수행하도록 보장한다. 많은 프로그래머가 동기화를 배타적 실행, 즉 한 스레드가 변경하는 중이라서 상태가 일관되지 않은 순간의 devfunny.tistory.com 이번 아이템은 아이템 78의 반대 상황을 다룬다. 아이템 78에서 충분하지 못한 동기화의 피해를 다뤘다면, 이번 아이템에서는 과도한 동기화에 대한 문제점을 다룬다. 과도한 동기화 과도한 동기화는 성능을 떨어뜨리고, 교착상태에 빠뜨리고, 예측할 수 없는 동작을 일으킬 수 있다. 응답 불가와..
synchronized 키워드 해당 메서드나 블록을 한번에 한 스레드씩 수행하도록 보장한다. 많은 프로그래머가 동기화를 배타적 실행, 즉 한 스레드가 변경하는 중이라서 상태가 일관되지 않은 순간의 객체를 다른 스레드가 보지 못하게 막는 용도로만 생각한다. 한 객체가 일관된 상태를 가지고 생성되고, 이 객체에 접근하는 메서드는 그 객체에 락(lock)을 건다. 락을 건 메서드는 객체의 상태를 확인하고 필요하면 수정한다. 즉, 객체를 하나의 일관된 상태에서 다른 일관된 상태로 변화시킨다. 동기화를 제대로 사용하면 어떤 메서드도 이 객체의 상태가 일관되지 않은 순간을 볼 수 없을 것이다. 여기에 중요한 기능이 한가지 더 있다. 동기화 없이는 한 스레드가 만든 변화를 다른 스레드에서 확인하지 못할 수도 있다. ..
예외 무시 API 설계자가 메서드 선언에 예외를 명시하는 까닭은 그 메서드를 사용할때 적절한 조치를 취해달라고 말하는 것이다. 하지만 이 예외를 무시하기란 아주 쉽다. 해당 메서드 호출을 try~catch를 사용하여 무시할 수 있기 때문이다. 예외 무시 // catch 블록을 비워두면 예외가 무시된다. try { ... } catch (SomeException ignored) {} 예외는 문제 상황에 잘 대처하기 위해 존재하는데 catch 블록을 비워두면 예외가 존재할 이유가 사라진다. 예외를 무시해야할 경우 예외를 무시해야 할때도 있다. 예를들어 FileInputStream을 닫을때, 파일의 상태를 변경하지 않았으니 복구할 것이 없으며, 필요한 정보는 다 읽었으므로 남은 작업을 중단할 이유도 없다. 혹..
실패 원자적 작업 도중 예외가 발생해도 그 객체는 여전히 정상적으로 사용할 수 있는 상태라면 코드가 더 유용해진다. 검사 예외를 던진 경우라면 호출자가 오류 상태를 복구할 수 있을테니 특히 더 유용할 것이다. 호출된 메서드가 실패하더라도, 해당 객체는 메서드 호출 전 상태를 유지해야한다. 이러한 특성을 '실패 원자적(failure-atomic)' 이라고 한다. 실패 원자적으로 만드는 방법 메서드를 실패 원자적으로 만드는 방법은 다양하다. 1) 불변 객체로 설계한다. 불변 객체는 태생적으로 실패 원자적이다. 메서드가 실패하면 새로운 객체가 만들어지지는 않을 수 있으나, 기존 객체가 불안정한 상태에 빠지는 일은 결코 없다. 불변 객체의 상태는 생성 시점에 고정되어 절대 변하지 않기 때문이다. 2) 가변 객체..
예외의 상세 메시지 권장 예외를 잡지 못해 프로그램이 실패하면 자바 시스템은 그 예외의 스택 추적(stack trace) 정보를 자동으로 출력한다. 스택 추적은 예외 객체의 toString 메서드를 호출하여 얻는 문자열이다. 이 정보가 실패 원인을 분석하는 유일한 정보인 경우가 많으며 해당 실패를 재현하기 어렵다면 더 자세한 정보를 얻기가 어렵거나 불가능하다. 따라서 예외의 toString 메서드에 실패 원인에 관한 정보를 가능한 한 많이 담아 반환하는 일이 아주 중요하다. 사후 분석을 위해 실패 순간의 상황을 정확히 포착해 예외의 상세 메시지에 담아야한다. 실패 순간을 포착하려면 발생한 예외에 관여된 모든 매개변수와 필드의 값을 실패 메시지에 담아야한다. 예외가 발생한 원인은 제각각이므로, 예외의 상세..
예외 문서화 메서드가 던지는 예외는 그 메서드를 올바로 사용하는데 아주 중요한 정보다. 따라서 각 메서드가 던지는 예외 하나하나를 문서화해야한다. 검사 예외는 항상 따로따로 선언하고, 각 예외가 발생하는 상황을 자바독의 @throws 태그를 사용하여 정확히 문서화하자. Integer.java /** * Constructs a newly allocated {@code Integer} object that * represents the {@code int} value indicated by the * {@code String} parameter. The string is converted to an * {@code int} value in exactly the manner used by the * {@cod..
예외 번역 수행하려는 일과 관련 없어 보이는 예외가 발생하면 당황스럽다. 메서드가 저수준 예외를 처리하지 않고 바깥으로 전파해버릴대 종종 일어나는 일이다. 이는 내부 구현 방식을 드러내어 윗 레벨 API를 오염시킨다. 다음 릴리스에서 구현 방식을 바꾸면 다른 예외가 튀어나와 기존 클라이언트 프로그램을 깨지게 할 수도 있다. 상위 계층에서는 저수준 예외를 잡아 자신의 추상화 수준에 맞는 예외로 바꿔 던져야 한다. 이를 예외 번역(exception translation)이라 한다. 예외 번역 예시 try { ... // 저수준 추상화를 이용한다. } catch (LowerLevelException e) { /* 추상화 수준에 맞게 번역한다. */ throw new HigherLevelException(.....
예외 재사용의 이점 예외는 재사용하는 것이 좋다. 자바 라이브러리는 대부분 API에서 쓰기에 충분한 수의 예외를 제공한다. 표준 예외를 재사용하면 얻는게 많다. 1) 개발한 API가 다른 사람이 익히고 사용하기가 쉬워진다. 2) API를 사용한 프로그램도 낯선 예외를 사용하지 않게 되어 읽기 쉽게 된다. 3) 예외 클래스 수가 적을수록 메모리 사용량도 줄고 클래스를 적재하는 시간도 적게 걸린다. 가장 많이 재사용되는 예외는 IllegalArgumentException이다. 호출자가 인수로 부적절한 값을 던질때 던지는 예외다. Exception, RunTimeException, Throwable, Error는 직접 재사용하지 말자. 널리 재사용되는 예외 예외 주요 쓰임 IllegalArgumentExcep..
검사 예외 사용 지양 검사 예외는 발생한 문제를 프로그래머가 처리하여 안전성을 높이게끔 해준다. 물론, 검사 예외를 과하게 사용하면 오히려 쓰기 불편한 API가 된다. 어떤 메서드가 검사 예외를 던질 수 있다고 선언됐다면, 이를 호출하는 코드에서는 catch 블록을 두어 처리하거나 더 바깥으로 던져 문제를 전파해야한다. (throws Exception) 어느 쪽이든 API 사용자에게 부담을 준다. 더구나 검사 예외를 던지는 메서드는 스트림 안에서 직접 사용할 수 없어서 자바 8부터는 부담이 더 커졌다. 1) API를 제대로 사용해도 발생할 수 있는 예외 2) 프로그래머가 의미있는 조치를 취할 수 있는 경우 이 두가지 경우를 제외하고는 검사 예외보다는 비검사 예외를 사용하는게 좋다. 검사 예외가 프로그래머..
문제상황 권고 타입 자바는 문제 상황을 알리는 타입(throwable)으로 아래 3가지를 제공한다. 1) 검사 예외 2) 런타임 예외 3) 에러 위 3가지를 어떤 상황에서 선택해서 사용해야할지 헷갈린다. 이에 도움이 될 수 있는 지침을 살펴보자. 검사 예외 1) 호출하는 쪽에서 복구하리라 여겨지는 상황일 경우 이는 검사와 비검사 예외를 구분하는 기본 규칙이다. 검사 예외를 던지면 호출자가 그 예외를 catch로 잡아 처리하거나 더 바깥으로 전파하도록 강제하게된다. 따라서 메서드 선언에 포함된 검사 예외 각각은 그 메서드를 호출했을 때 발생할 수 있는 유력한 결과임을 API 사용자에게 알려주는 것이다. API 설계자는 API 사용자에게 검사 예외를 던져주어 그 상황에서 회복해내라고 요구한 것이다. 호출한 ..