※ 이 글은 남궁성 저자의 '자바의 정석' 156~163강을 수강한 후 정리한 내용입니다.
1. 임계영역 : 한 번에 한 개의 쓰레드만 접근 가능한 영역
synchronized로 임계영역을 설정하는 방법 2가지
public synchronized void calcSum(){
// Do Something
}
synchronized(참조변수){
// Do Something
}
2. wait()과 notify()
동기화의 효율을 높이기 위해 사용
Object 클래스에 정의되어 있으며 동기화 블록 내에서만 사용 가능하다.
wait(): 객체의 lock을 풀고 쓰레드를 해당 객체의 waiting pool에 넣는다
notify(): waiting pool에서 대기중인 쓰레드 중의 하나를 깨운다.
notifyAll(): waiting pool에서 대기중인 모든 쓰레드를 깨운다.
Customer 쪽에서는 자원이 없을 때 wait()으로 lock을 반납하고,
Provider 쪽에서는 자원이 추가되었을 때 notify()로 Customer에게 자원추가를 통지한다.
3. ConcurrentModificationException 예외
여러 데이터를 담고 있는 객체에서 읽기 수행 중 add(), remove()등의 변경이 발생할 경우 발생
4. wait(), notify()를 쓰면 대상이 불분명하다는 단점이 존재
이를 해결하기 위해 나온게 Lock & Condition
5. Lock & Condition
추후 추가 예정
6. 람다식(Lambda Expression)
함수를 간단한 '식(Expression)'으로 표현하는 방법
블록 안에 문장이 하나뿐일 때 괄호생략 가능하고 끝에 세미콜론(;) 붙이지 않는다
람다식은 익명 함수가 아니라 익명 객체이다..!!
익명 객체이기 때문에 함수형인터페이스 타입 변수로 다뤄야 한다.
MyFunctino2 f = (a, b) -> a > b ? a : b;
7. 함수와 메서드의 차이
근본적으로 동일. 함수는 일반적 용어, 메서드는 객체지향개념 용어
함수는 클래스에 독립적, 메서드는 클래스에 종속적
8. 함수형 인터페이스
단 하나의 추상 메서드만 선언된 인터페이스
@FunctionalInterface 어노테이션을 붙이면 컴파일러가 문법 체크해줌. 쓰면 좋음.
추상 메서드를 선언할 때 'public abstract'는 생략 가능하다.
인터페이스 함수의 기본이 'public abstract' 니까.
9. 함수형인터페이스 타입의 매개변수는 람다식을 전달하면 된다는 뜻이다.
// 선언
void aMethod(MyFunction f){
f.myMethod();
}
// 호출
aMethod(()-> System.out.println("myMethod()"));
10. 함수형인터페이스 타입을 리턴타입으로 쓸 수도 있다.
MyFunction myMethod(){
return ()->{};
}
11. java.util.function 패키지
자주 사용되는 다양한 함수형 인터페이스를 제공
Runnable : 매개변수도 없고, 반환값도 없음
void run();
Supplier<T> : 매개변수는 없고, 반환값은 있음
T get();
Consumer<T> : Supplier와 반대로 매개변수만 있고, 반환값이 없음
void accpet(T t);
Function<T, R> : 일반적인 함수, 하나의 매개변수를 받아서 결과를 반환
R apply(T t);
Predicate<T> : 매개변수는 하나이고 조건식을 표현하는데 사용됨
boolean test(T t);
BiConsumer<T, U> : 두 개의 매개변수만 있고 반환값이 없음
void accept(T t, U u);
BiPredicate<T, U> : 조건식을 표현하는 데 사용됨. 매개변수는 둘, 반환값은 boolean
boolean test(T t, U u);
BiFunction<T, U, R> : 두 개의 매개변수를 받아서 한개의 결과를 반환
R apply(T t, U u);
UnaryOperator<T> : Function의 자손. Function과 달리 매개변수와 결과의 타입이 같다
T apply(T t);
BinaryOpeartor<T> : BiFunction의 자손. BiFunction과 달리 매개변수와 결과의 타입이 같다
T apply(T t, T t);
JAVA에서 이렇게 만들어둔 이유는 왠만하면 매개변수 1개, 2개일 땐 만들어둔거 쓰라는 의미
12. 메서드 참조(method reference)
하나의 메서드만 호출하는 람다식은 '메서드 참조'로 간단히 할 수 있다.
Function<String, Integer> f = (String s) -> Integer.parseInt(s);
Function<String, Integer> f = Integer::parseInt; // 메서드 참조, 위 코드와 동일한 의미
13. 생성자의 메서드 참조
Function<Integer, MyClass> s = (i) -> new MyClass(i);
Function<Integer, MyClass> s = MyClass::new; // 메서드 참조, 위 코드와 동일한 의미
14. 스트림
다양한 데이터 소스(컬렉션, 배열)를 표준화된 방법으로 다루기 위한 것
Collections Framework의 사용방법이 드디어 통일됨
JDK 1.8에 나옴
15. Collection을 Stream으로 변환할 수 있음
Stream<Integer> intStream = list.stream();
16. 스트림 사용법
1) 스트림 만들기
2) 중간 연산을 n번 수행하기
3) 최종 연산 1번해서 결과 얻기
17. 스트림의 특징
1) 스트림은 데이터 소스로부터 데이터를 읽기만할 뿐 변경하지 않는다.
2) 스트림은 Iterator처럼 일회용이다.(필요하면 다시 스트림을 생성해야 함)
3) 스트림은 최종 연산 전까지 중간연산이 수행되지 않는다. (지연된 연산)
지연된 연산이기 때문에 무한 스트림도 사용할 수 있다.
IntStream intStream = new Random().ints(1,46); // 무한 스트림.. 랜덤값을 무한히 내보낸다.
intStream.distinct().limit(6).sorted() // 중간연산
.forEach(i->System.out.print(i+",")); // 최종연산
4) 스트림은 작업을 병렬로 처리할 수 있다. (병렬 스트림)
함수형 프로그래밍은 빅데이터 분야에서 큰 작업들을 빨리 처리할 수 있어서 인기가 있다.
int sum = strStream.parallel()
.mapToInt(s -> s.length()).sum(); // 모든 문자열의 길이의 합
5) 기본형 스트림을 제공한다.
IntStream, LongStream, DoubleStream
오토박싱&언박싱의 비효율이 제거됨 (Stream<Integer> 대신 IntStream 사용)
숫자와 관련된 유용한 메서드를 Stream<T>보다 더 많이 제공
'Study Memos > Java' 카테고리의 다른 글
[남궁성 '자바의 정석'] 164~171강 (0) | 2021.11.19 |
---|---|
[남궁성 '자바의 정석'] 132~155강 (0) | 2021.11.17 |
[남궁성 '자바의 정석'] 112~131강 (0) | 2021.11.16 |
[남궁성 '자바의 정석'] 94~111강 (0) | 2021.11.15 |
[남궁성 '자바의 정석'] 76~93강 (0) | 2021.11.11 |