CAS ( Compare And Swap ) Atomic은 CAS 방식에 기반하여 동기화 문제를 해결한다. CAS란 변수가 기존에 가지고 있던 값이 내가 예상하는 값과 일치하는 경우에만 새로운 값을 할당하는 것. public class AtomicDemo { private int val; public boolean compareAndSwap(int oldVal, int newVal) { if (val == oldVal) { val = newVal; return true; } return false; } } 간단하게, 값을 변경하기 전에 한번 더 확인해주는거라 보면됨. Java에서 제공하는 Atomic Type은 이러한 CAS를 하드웨어(CPU)의 도움을 받아 한 번에 단 하나의 스레드만 변수의 값을 변경..
volatile 키워드 volatile 키워드로 선언된 변수는 Main Memory에 저장된다. 보통 변수에 read/write를 하게되면 CPU Cache까지만 바라보고 작업을 진행하는데, 이를 Main Memory까지 확장시키는 것. 아래 그림을 보자. 멀티 스레드 프로그래밍에서 각 스레드는 최초 메인 메모리에서 변수의 값을 읽어온후, 이를 CPU Cache에 저장한다. 그 다음부터는 변수 값을 참조하기 위해 CPU Cache까지만 보기 때문에 두 스레드가 같은 변수의 값을 read/write한다면 값의 불일치 문제가 발생할 수 있다. CPU Cache가 아닌 Main Memory에서 변수의 값을 읽고/쓴다면 변수 값의 동기화 문제가 해결될 수 있다. ( volatile로 변수를 선언. ) 참고자료 ..
Java는 멀티 스레드 프로그래밍에서의 동기화 문제에 대해 3가지 방법을 제시한다. synchronized 키워드 volatile 변수 Atomic 클래스 이 세가지 중에서 synchronized 키워드에 대해 정리해보자. synchronized 키워드 Java에서 synchronized 키워드를 활용하는 방법은 두 가지다. synchronized 메서드 ( 메서드 자체에 해당 키워드를 적용 ) synchronized 블럭 ( 메서드 내부에 동기화가 필요한 로직에만 synchronized 블럭으로 감싸는 형태 ) 먼저 메서드 자체에 synchronized 키워드를 붙여줬을 때. public class DemoSynchronization { private String mMessage; public stat..
Annotation 어노테이션은 잘만 사용하면 정말 유용한 Java의 구문이다. 기본적인 종류는 몇 가지에 한정되지만, 내가 원하는대로 커스텀 어노테이션을 만들어 사용할 수 있다. 어노테이션의 본질적인 목적은 소스 코드에 메타데이터를 표현하는 것. 하지만 단순히 부가적인 표현을 넘어, reflection을 이용하면 어노테이션 지정만으로 원하는 클래스를 주입하는 것도 가능하다. Built-in Annotation Java에서 기본적으로 제공하는 어노테이션은 다음과 같다. @Override : 오버라이딩할 때 사용. @Deprecated : 더이상 사용되지않는 메서드를 지정한다. 해당 어노테이션이 붙은 메서드를 사용했을 시 컴파일 경고. @SuppressWarnings : 컴파일 경고를 무시한다. @Safe..
JDK 1.8에서 Optional이라는 클래스가 추가가 되었다. null에 대응하기 위해. 예제를 위한 아래의 두 클래스가 있다. @Data class Person { private String name; private int age; } @Data class House { private Person owner; private String address; } 이때, 콘솔에 집 정보를 출력하기 위해 다음과 같은 코드를 구현했다. public class Main { public static void main(String[] args) { House house = houseService.getRandomHouse(); System.out.println("owner : " + house.getOwner().ge..
Functional Interface는 함수를 *일급 객체로 사용할 수 없는 Java 언어의 단점을 보완하기 위해 도입되었다. JDK 1.8의 java.util.function 패키지에는 수많은 Functional Interface들이 정의되어 있다. *일급 객체 ( first-class object ) 다른 객체들에 일반적으로 적용 가능한 연산을 모두 지원하는 객체를 가르킨다. 보통 함수에 매개변수로 넘기기, 수정하기, 변수에 대입하기와 같은 연산을 지원할 때 일급 객체라고 한다. (참고: https://ko.wikipedia.org/wiki/%EC%9D%BC%EA%B8%89_%EA%B0%9D%EC%B2%B4) "API 문서의 설명" This is a functional interface and can..
먼저, 메서드 참조의 형태는 다음과 같다. // 메서드 참조는 아래와 같이 두 가지 형태로 사용이 가능하다. 클래스명::메서드명 참조변수명::메서드명 메서드 참조는 특정 조건에 한하여 람다 표현식을 생략할 수 있게한다. 여기서 특정 조건이란 아래와 같다. // 아래와 같은 람다 표현식이 있고, 해당 람다는 선택된 요소를 특정 메서드의 파라미터로 전달하는 역할을 한다. (e -> demoMethod(e)) // 위와 같이 람다에서 선택된 요소가 특정 메서드를 호출하기 위한 파라미터로서의 역할을 할 뿐이라면, 아래와 같이 사용이 가능하다. (클래스명::demoMethod) (참조변수명::demoMethod) 조금 더 현실감 있는 예제를 살펴보자. dao 객체로부터 ItemList를 가져오는데, 가져온 각각의..
JAR ( Java Archive ) vs WAR ( Web Application Archive ) 아래 인용구를 보면 아주 간결하게 잘 설명되어 있다. These files are simply zipped files using the java jar tool. These files are created for different purposes. Here is the description of these files: .jar files : The .jar files contain libraries, resources and accessories files like property files. .war files : The war file contains the web application that can..
'JDK 1.8의 특징이 뭔가요?' 라고 묻는다면, 단연 람다와 스트림이 아닐까? (여기서 스트림은 흔히 I/O에서 말하는 스트림과는 다른 개념이다.) 람다 ( Lambda ) 람다 표현식을 간단히 정의하면 메서드를 하나의 식으로 표현한 것. int add(int a, int b) { return a + b; } // 위의 메서드를 람다 표현식으로 나타내면 아래와 같다. (a, b) -> a + b; Java에서 모든 것은 객체다. 위와 같은 람다 표현식은 사실 익명 클래스의 발전된 형태이다. 익명 클래스에서 파라미터의 갯수와 반환값이 같다면 어떤 메서드인지 추론이 가능하다는걸 이용한 것. new Object() { int add(int a, int b) { return a + b; } } 람다 표현식이..
enum 클래스는 의미있는 심볼릭 상수를 정의하고 싶을 때 많이 사용된다. enum 클래스에서 심볼릭 상수를 정의할 때, 어떤 불규칙한 값을 담고 싶다면 불규칙한 값들을 담을 수 있는 변수와 생성자를 선언해줘야 한다. 다음은 케릭터 정보에 대한 열거형 상수를 만드는 예제. public enum CharacterInfoType { CHARACTER_INFO_TYPE_NONE(""), CHARACTER_INFO_TYPE_CHARACTER_NAME("characterName"), CHARACTER_INFO_TYPE_CHARACTER_STATUS("characterStatus"), CHARACTER_INFO_TYPE_LOCATION("location"); @Getter private String type; Ch..
default 메서드 CharSequence 인터페이스를 까보다가 왠 메서드명 앞에 default 키워드가 있길래 처음보는거라 정리해둔다. 코드는 아래와 같다. public default IntStream chars() { class CharIterator implements PrimitiveIterator.OfInt { int cur = 0; public boolean hasNext() { return cur < length(); } public int nextInt() { if (hasNext()) { return charAt(cur++); } else { throw new NoSuchElementException(); } } @Override public void forEachRemaining(In..
입력과 출력 (Input / Output) 입출력을 공부할 때마다 느끼는거지만, 알면 알수록 어려운거 같다. 예를 들어, 어떤 파일의 데이터를 입력으로 받고 새로운 파일로 출력한다고 해보자. 그럼 파일 시스템은 ? Unix 시스템은 개행이 '\n'으로 이뤄져있고, Windows는 '\r\n'으로 이뤄져있는 등 저수준으로 가면 생각해야할게 참 많은 듯하다. Java는 입출력을 크게 2가지로 분류한다. ( C/C++도 이렇게 분류한다. ) 1. Byte 단위 입출력 Byte 단위 입출력의 최상위 클래스는 InputStream과 OutputStream 추상 클래스다. InputStream과 구현 클래스들을 나타내면 아래 그림과 같다. ( 구현 클래스 이거말고도 몇 개 더 있음 ) 2. 문자 단위 입출력 문자 ..