지연 초기화 (lazy initialization) 필드 초기화 시점을 그 값이 처음 필요할 때 까지 늦추는 기법 정적 필드와 인스턴스 필드에 모두 사용 가능 주로 최적화 용도지만, 클래스와 인스턴스 초기화 때 발생하는 위험한 순환 문제를 해결하는 효과도 있음 지연 초기화는 필요할 때까지는 하지 말라 클래스나 인스턴스 생성 시 초기화 비용은 줄지만, 지연 초기화하는 필드에 접근하는 비용은 커짐 지연 초기화하려는 필드들 중 초기화가 이루어지는 비율에 따라, 실제 초기화 비용에 따라, 초기화 된 각 필드를 얼마나 빈번히 호출하느냐에 따라 지연 초기화가 성능이 느려지게 할 수도 있음 지연 초기화가 필요할 때 해당 클래스의 인스턴스 중 그 필드를 사용하는 인스턴스의 비율 < 그 필드 초기화 비용 일 때 정말 그..
스레드 안전성 한 메서드를 여러 스레드가 동시에 호출할 때 그 메서드가 어떻게 동작하는 지는 해당 클래스와 사용자와의 중요한 계약이다. 메서드 선언에 synchronized 한정자를 선언할지는 구현 이슈일 뿐 API에 속하지 않음 그래서 그것만으로 스레드 안전하다고는 할 수 없음 멀티스레드 환경에서도 API를 안전하게 사용하게 하려면 클래스가 지원하는 스레드 안전성 수준을 정확히 명시해야함 스레드 안전성이 높은 순 불변(immutable) : 이 클래스의 인스턴스는 마치 상수같아서 외부 동기화도 필요 없음. ex) String, Long, BigInteger [아이템 7] 무조건적 스레드 안전 : 이 클래스의 인스턴스는 수정될 수 있으나 내부에서 잘 동기화하여 외부 동기화 없이 동시에 사용해도 안전하다...
1. 객체지향의 사실과 오해 객체지향의 사실과 오해 『객체지향의 사실과 오해』는 객체지향이란 무엇인가라는 원론적면서도 다소 위험한 질문에 답하기 위해 쓰여진 책이다. 안타깝게도 많은 사람들이 객체지향의 본질을 오해하고 있다. 가장 널리 퍼져있는 오해는 클래스가 객체지향 프로그래밍의 중심이라는 것이다. 객체지향으로 향하는 첫 걸음은 클래스가 아니라 객체를 바라보는 것에서부터 시작한다. 객체지향으로 향하는 두 번째 걸음은 객체를 독립적인 존재가 아니라 기능을 구현하기 위해 협력하는 공동체의 일원으로 바라보는 것이다. 세 번째 걸음을 내디딜 수 있는지 여부는 협력에 참여하는 객체들에게 얼마나 적절한 역할과 책임을 부여할 수 있느냐에 달려 있다. 객체지향의 마지막 걸음은 앞에서 설명한 개념들을 프로그래밍 언어라..
동시성 유틸리티 자바5에 도입된 고수준의 동시성 유틸리티 덕분에 자바의 wait와 notify [아이템 50] 를 사용해야 할 이유가 줄었다. wait와 notify는 올바르게 사용하기 까다로우니 고수준 동시성 유틸리티를 사용하자. java.util.concurrent의 고수준 유틸리티의 범주 : 실행자 프레임워크 [아이템 80], 동시성 컬렉션(concurrent collection), 동기화 장치(sychronized) 동시성 컬렉션 표준 컬렉션 인터페이스에 동시성을 가미해 구현한 고성능 컬렉션 높은 동시성을 위해 동기화를 각자 내부에서 수행 [아이템 79] 동시성 컬렉션에서 동시성을 무력화하는 것은 불가능, 외부에서 락을 추가로 사용하면 오히려 속도가 느려짐 동시성 무력화가 불가능하므로 여러 메서드..
java.util.concurrent 아이템 49에서 백그라운드 스레드에 위임해 비동기적으로 작업을 요청해 처리하는 작업 큐를 생성해 사용했었다. 이제는 직접 사용자가 작업 큐를 작성하지 않고 java.util.concurrent 패키지를 사용하면 된다. 실행자 프레임워크라고 하는 인터페이스 기반의 유연한 태스크 실행 기능을 담고 있다. ExecutorService exec = Executors.newSingleThreadExecutor(); //실행자 생성 exec.execute(runnable); //실행 할 태스크를 넘기는 방법 exec.shutdown(); //실행자를 종료시키는 방법 ExecutorService(실행자 서비스)의 주요 기능들 큐에 작업을 제출하고서 작업이 완료될 때까지 기다릴 수..
과도한 동기화 과도한 동기화는 성능 저하, 교착상태, 예측할 수 없는 동작을 야기한다. 응답 불가와 안전 실패를 피하려면 동기화 메서드나 동기화 블록 안에서는 제어를 절대로 클라이언트에게 양도하면 안됨 예를 들어, 동기화된 영역 안에서는 재정의할 수 있는 메서드를 호출하거나 클라이언트가 넘겨준 함수 객체 [아이템 24]를 호출해서도 안됨 이런 외계인 메서드에서는 무엇을 할 지 알지 못하고 통제할 수도 없음 과도한 동기화 예제 Observer Pattern 으로 구현한 Set Observer Pattern : 객체의 상태 변화를 관찰하는 관찰자들, 즉 옵저버들의 목록을 객체에 등록하여 상태 변화가 있을 때마다 메서드 등을 통해 객체가 직접 목록의 각 옵저버에게 통지하도록 하는 디자인 패턴이다. 클라이언트는..
synchronized 키워드 해당 메서드나 블록을 한번에 한 스레드씩 수행하도록 보장 동기화의 기능 1) 배타적 실행 한 스레드가 변경하는 중이라서 상태가 일관되지 않을 때 객체를 다른 스레드가 보지 못하게 막는 것 객체를 하나의 일관된 상태에서 다른 일관된 상태로 변화 : 한 객체가 일관된 상태를 가지고 생성 → 객체에 접근하는 메서드는 그 객체에 락(lock)을 걸음 → 락을 건 메서드는 필요하면 객체를 수정 2) 스레드 사이 안정적인 통신 동기화 없이는 한 스레드가 만든 변화를 다른 스레드에서 확인하지 못할 수 있다. 변경된 데이터의 최종 결과 값을 읽을 수 있게 한다. 원자적 (atomic) 자바에서 long / double 외 변수를 읽고 쓰는 동작은 원자적이다. (동기화 없이도 항상 어떤 스..
예외 처리란, 예외 상황에 적절한 처리를 하기 위해 존재 → 무시하지 말자. catch 블록 비워두기 try { // ... } catch(Exception e) { // catch 블록을 비워두면 예외가 무시된다. } 예외를 무시해야할 때 예를 들어 읽기전용 스트림인 FileInputStream을 닫을 때 예외가 발생하면 어떤 조치를 해줄 필요가 없다. 이런 경우에 catch 문안에 주석으로 이유를 남기고 예외 변수의 이름도 ignored로 바꿔놓는다. Future f = exec.submit(planarMap::chromaticNumber); int numColors = 4; // 기본값 try { numColors = f.get(1L, TimeUnit.SECONDS); } catch(TimeoutE..