[6주차] Lambda, Stream, SAM, 메서드 참조 유형, Comparable vs Comparator, Optional, Process, Thread, Task

이맑음·2024년 1월 9일

Java 수업 필기

목록 보기
4/15

람다식

  • 함수형 프로그래밍을 가능하게 하는 기능
  • 익명 함수인 람다 표현식을 사용하여 메서드에 인수로 전달 or 변수에 저장하여 데이터를 처리
  • 자바에서 람다표현식이란? 람다표현식은 익명함수를 간결하게 표현하는 방법으로 람다표현식을 사용하면 메서드에 매개변수로 동작을 전달할 수 있기 때문에 코드의 표현력과 기능성을 향상시킬 수 있다.
1. parameter (param1, param2) : 매개변수 지정, 매개변수는 없을 수도 있다
2. lamdba operator -> : 람다 본문에서 매개변수 리스트를 분리, 함수 시그니처와 본문 사이의 다리 역할
3. body{...} : 람다식이 실행될 부분
-> (parameters,...) -> {body}
  • 데이터 처리부에 제공되는 함수 역할을 하는 매개변수를 가진 중괄호 블록
  • 자바는 람다식을 익명 구형 객체로 변환

함수형 인터페이스 SAM(Single Abstract Method)

  • 어노테이션 = @FunctionalInterface
  • 선택 사항
  • 사용시 인터페이스가 SAM을 유지하도록 도움을 준다
@FunctionalInterface
interface MathOperation {
    int calculate(int a, int b);
}

public class ex2 {
    public static void main(String[] args) {
        MathOperation addition = (a, b) -> a + b; //=Integer::sum
        int result = addition.calculate(3, 4);
        System.out.println(result);
    }

}

메서드 참조 유형 4가지

  1. 정적 메서드에 대한 참조
    클래스명::메서드명 : 람다 표현식이 정적 메서드에 위임할 때 유용
//lambda expression
Function<Integer, String> lambda = (x)->String.valueOf(x);

//Method expression
Function<Integer, String> reference = String::valueOf;
  1. 특정 객체의 인스턴스 메서드에 대한 참조 : object::methodName 표현
//lambda expression : 람다를 정의
Function<Integer, String> lambda = (str)->String.length(x);

//Method expression : 람다식을 호출할 때
Function<Integer, String> reference = String::length;
  1. 특정 타입의 임의 객체의 인스턴스 메서드에 대한 참조 : className::methodName
//lambda expression
BiFunction<String, String, Boolean> lambda = (str1, str2)->str1.equals(str2);

//Method expression
BiFunction<String, String, Boolean> reference = String::equals;
  1. 생성자에 대한 참조 : className::new
//lambda expression
Supplier<List<String>> lambda = ()-> newArrayList<>();

//Method expression
Supplier<List<String>> reference = ArrayList::new;

생성자 참조

  1. 인수가 없는 생성자 참조
    Supplier 함수형 인터페이스는 인수가 없는 객체의 공급자를 나타낸다.
    참조된 생성자를 사용하여 새 객체를 생성하는 방법을 제공한다
Supplier<ClassName> constructorRef = ClassName::new;
  1. 인수가 있는 생성자 참조(인수를 받는 생성자를 나타낸다)
Function<Integer, ClassName> constructorRef = ClassName::new;
  1. 배열 생성자에 대한 참조
Function<Integer, ClassName[]> constructorRef = ClassName::new;
  1. 제너릭 클래스의 생성자 참조
Supplier<GenericClass<Integer>> constructorRef = GenericClass<Integer>::new;
  • 사용예시
Calculator calculator = new Calculator();
Calculator calculator = CalculatorImpl::new;
        
//미리 정의된 값으로 컬렉션을 초기화
List<Integer> numbers = Stream.of(1,2,3).collect(Collectors.toCollection(ArrayList::new));

Function<String, Integer, Person> personFunction = Person::new;

//인수가 없는 Random 생성자를 사용하여 새 Random 객체를 생성하는 람다식 작성
Supplier<Random> newRandom = Random::new;
Random random = newRandom.get();
System.out.println(random.nextInt(100));

Stream

Stream이란

  • java.util.stream 패키지 하위에 존재
  • BaseStream 인터페이스를 상속받는다
  • 데이터의 흐름
  • 데이터가 여러개가 있어야 흐름을 만들 수 있다
  • 스트림 데이터 소스 : 컬렉션, 배열이 주로 사용된다
  • 스트림 데이터는 데이터소스로 부터 추루한 연속적인 데이터이다
  • 스트림 api : 연속적인 데이터의 흐름을 반복적으로 또는 연산하여 처리하는 기능
  • filter, map, reduce, foreach(oop.lambda.ex4)
  • 컬렉션의 stream()메서드로 stream객체를 얻고, forEach()메소드로 요소를 어떻게 처리할지를 람다식으로 제공
  • stream api collection에서 다양한 연산을 수행하기 위해 람다 표현식을 허용하는 메서드를 제공
  • 스트림의 요소를 다른 유형으로 변환하는데 사용
  • 데이터소스로부터 데이터를 읽기만 할 뿐, 변경하지 않는다
  • 한번 사용하면 닫혀서 다시 사용할 수 없다
  • 스트림 작업은 내부 반복으로 처리한다

Stream과 Iterator 차이점

  1. 내부 반복자이므로 처리속도가 빠르고 병렬 처리에 효율적
  2. 람다식으로 다양한 요소 처리 정의
  3. 중간 연산과 최종 연산을 수행하도록 파이프 라인을 형성

내부 반복자란

  • 요소 처리 방법을 컬렉션 내부로 주입시켜 요소를 반복 처리
  • 멀티 코어 cpu를 최대한 활용하기 위해 요소들을 분배시켜 병렬 작업 가능

Stream 특징

  1. 스트림 연산은 기존 자료를 변경하지 않는다
  2. 중간연산과 최종연산으로 구분한다
  3. 한 번 생성하여 사용한 스트림은 재사용할 수 없다(close 된다) -> 부모인 BaseStream이 AutoCloseable 인터페이스를 상속받고 있기 때문에

중간연산

  • filter() : 조건에 맞는 요소를 추출(like if) -> return Stream
  • map() : 조건에 맞는 요소를 변환(mapToInt() 등) -> return Stream
  • sorted() : 정렬
  • peek() :

최종연산

  • 스트림의 자료를 소모하면서 연산을 수행한다
  • 최종 연산 이후에 소모된 스트림은 더 이상 연산을 할 수 없다
  • foreach() : 요소를 하나씩 추출
  • 집계 :
    1. count() : 요소 개수 카운트 return long
    1. sum() return int, long, double
    2. average() return optional
    3. findFirst() return optional
  • 매칭 : return boolean
    1. allMatch() : 모든 요소가 만족하는지 여부
    1. anyMatch() : 최소 하나의 요소가 만족하는지 여부
    2. noneMatch() : 모든 요소가 만족하지 않는지 여부
//정수형 배열 생성 및 초기화
int[] array = {1, 2, 3, 4, 5};
//정수형 배열을 스트림 객체 stm1에 담아주기
IntStream stm1 = Arrays.stream(array);
Stream<Integer> stm3 = Arrays.stream(array).boxed();
//stm1에서 홀수만 뽑아(중간 연산) stm2에 담아주기
IntStream stm2 = stm1.filter(n -> n % 2 != 0);
Stream<Integer> stm4 = stm3.filter(n -> n % 2 != 0);
//stm2의 총합(최종 연산) 구하기
int result = stm2.sum();
int total = stm4.collect(Collectors.summingInt(Integer::intValue));
//int total = stm4.mapToInt(Integer::intValue).sum();

파이프라인 구성

  • 여러 개의 스트림이 연결되어 있는 구조
 //정수형 배열 생성 및 초기화
 int[] array = {1, 2, 3, 4, 5};
 //파이프 라인 구성
 int sum = Arrays.stream(array).filter(n -> n % 2 == 1).sum();

요소 수집

  • 스트림은 요소들을 필터링, 매핑한 후 요소드을 수집하는 최종처리 메소드 collec()제공
  • collect()를 사용하면 필요한 요소만 컬렉션에 담을 수 있고, 요소들을 그룹핑한 후 집계할 수 있다
  • Stream.collect(Collector<T,A,R> collector)
    1. T 요소를 A에 누적시켜 R에 저장
    1. A : the intermediate accumulation type of the Collector
    2. R : the type of result
  • collecto는 어떤 요소를 어떤 컬렉션에 수집할 것인지 결정

Comparable vs Comparator

 //Comparable을 구현하였을 때 정렬 하는 방법
System.out.println("국어 점수 오름차순");
stuList.stream().sorted().forEach(System.out::println);

System.out.println("국어 점수 내림차순 : reverseOrder");      
stuList.stream().sorted(Comparator.reverseOrder()).forEach(System.out::println);

System.out.println("국어 점수 내림차순1 : compareTo");
stuList.stream().sorted((o1, o2) -> o2.compareTo(o1)).forEach(System.out::println);

//Comparable이 구현되지 않았을 때 정렬 하는 방법
System.out.println("국어 점수 오름차순 : Integer.compare");
stuList.stream().sorted((o1, o2) -> Integer.compare(o1.getKorScore(), o2.getKorScore()))
				//.sorted(Comparator.comparingInt(Student::getKorScore))
  				.forEach(stu -> System.out.println(stu.getName() + " " + stu.getKorScore()));

System.out.println("국어 점수 내림차순 : Integer.compare");
stuList.stream().sorted((s1, s2) -> Integer.compare(s2.getKorScore(), s1.getKorScore()))
                .forEach(stu -> System.out.println(stu.getName() + " " + stu.getKorScore()));

Optional

  • NPE(NullPointException)를 핸들링하기 위해 사용
  • null 대신 초기값을 사용하도록 권장

운영체제

  1. 사용자와 컴퓨터 (하드웨어+소프트웨어) 간의 인터페이스로서 동작하는 시스템 소프트웨어의 일종
  2. 자원을 효율적으로 운영 관리하는 소프트웨어
  3. 목적 : (시스템)운영과 (리소스-하드웨어, 소프트웨어)관리를 위한 소프트웨어
  4. 프로세스 상태를 감시
  5. 프로세스 상태를 기반 프로세스 스케줄링 -> 프로세스를 관리하고 제어

Process

  1. 실행 중인 프로그램(=OS로 부터 자원을 할당 받음)
  2. 독립된 메모리 영역을 할당 받는다

Process 상태 전이

  • 프로세스가 실행하는 동안 상태가 OS에 의해 변경되는 것

Multi Process

  • 프로그램 단위멀티 태스킹
  • 멀티 프로세스
    • <프로세스1> : 멀티 스레드
      • code, Data, Heap 메모리는 공유
      • 스레드1---------------> 독립적인 stack 메모리를 할당받는다
      • 스레드2---------------> 독립적인 stack 메모리를 할당받는다
    • <프로세스2> : 싱글 스레드
      • 스레드-----------------> 독립적인 stack 메모리를 할당받는다

Task

  • 작업

multi tasking

  1. 두 가지 이상작업동시에 처리하는 것
  2. 운영체제가 multi process를 생성해서 처리해준다
  3. mulit tasking이 반드시 multi process를 의미하지는 않는다
  • 하나의 프로세스에서 멀티태스킹을 할 수 있도록 만든 대표적인 프로그램 : 채팅
    메신저 프로그램은 채팅 작업을 하면서 동시에 파일전송이나 선물하기, 연락처 전송하기 등등
  • 하나의 프로세스가 두 가지 이상의 작업을 처리할 수 있는 것은 멀티 스레드 때문이다
  • 프로세스 내에서 스레드가 두개라면 두개의 코드 흐름이 생기는 것이다

Thread

  • 코드의 실행 흐름, 프로세스의 내부에 존재, JVM이 운영
  • new -> start -> runnable -> run
    -> waiting, timed-waiting, terminate

Multi Thread

  1. 두 개의 코드 실행 흐름
  2. 두 가지 이상의 작업을 처리
  3. 프로그램 내부에서 멀티 태스킹

Thread State

  • NEW
    A thread that has not yet started is in this state.
  • RUNNABLE
    A thread executing in the Java virtual machine is in this state.
  • BLOCKED
    A thread that is blocked waiting for a monitor lock is in this state.
  • WAITING
    A thread that is waiting indefinitely for another thread to perform a particular action is in this state.
  • TIMED_WAITING
    A thread that is waiting for another thread to perform an action for up to a specified waiting time is in this state.
  • TERMINATED
    A thread that has exited is in this state.

Thread State Method

  • 일시정지 --interrupt(), notify(), notifyAll()--> 실행대기
  • 실행대기 -----------> 실행
    실행대기 <--yield()-- 실행
  • 실행 --sleep(), join(), wait()-->일시 정지
  • sleep(long millis) : 주어진 시간만큼 일시정지. 주어진 시간이 지다면 자동으로 실행대기 상태
  • join() : 일시 정지 상태, 실행 대기 상태가 되려면 join()를 가진 스레드가 종료되어갸 한다
  • wait() : 동기화 블록 내에서 스레드를 일시 정지 상태로 만든다
  • interrupt() : 일시 정지 상태일 경우, InterruptException을 발생시켜 실행 대기 상태 or 종료 상태로 만든다
  • notify(), notifyAll() : wait()으로 일시 정지 상태인 스레드를 실행 대기 상태로 바꾼다
  • yield() : 실행 상태에서 다른 스레드에게 실행을 양보하고 실행 대기 상태가 된다
    new -> start -> runnable -> run
    -> waiting, timed-waiting, blocked
    -> terminate
    yield : 다른 스레드가 cpu를 할당받을 수 있게 runnable(대기)상태로 cpu 양보
    runnable—sleep, join, wait—>wait
    sleep 지정 시간 만큼 대기, 자동으로 runnable 상태로 변경
    join 대기, join()메서드를 가진 스레드가 종료되어야 대기 종료
    wait 동기화 블럭에서 일시 정지
    wait— interrupt, notify, notifyAll—>runnable
    interrupt : 예외를 발생시켜 복귀하거나 스레드를 강제 종료하여 일시 정지 상태를 벗어남
    notify wait되어 있는 스레드를 해제시켜준다
    notifyAll wait 되어 있는 모든 스레드들을 모두 runnable 상태로 변경시켜준다

Thread 생성 방법

  1. Thread 클래스 :
    1-1. java.lang.Thread 클래스로부터 작업 스레드 객체를 직접 생성
    Thread thread = new Thread(Runnable target);
    Runnable 스레드가 작업을 실행할 때 사용하는 인터페이스
    구현 클래스는 run()을 재정의(overring)하여 스레드가 실행할 코드를 작성
    1-2. java.lang.Thread 클래스를 상속받아 생성

  2. Runnable interface : run()


public class ThreadEx1 {
    public static void main(String[] args) {
        //1. 상속으로 Thread 생성
        ThreadByInheritance t1 = new ThreadByInheritance();
        //2.  Runnable 인터페이스를 통해서 Thread 생성 -> 1.보다 더 많이 사용 -> 상속에 있어 impl 이 유리하기 때문
        Thread t2 = new Thread(new ThreadByImplement());

        t1.start();
//        t1.start(); //->IllegalThreadStateException
        t2.start();
    }

}


class ThreadByInheritance extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.print(0);

        }
    }
}

class ThreadByImplement implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.print(1);

        }
    }
}

  • jvm도 thread 형태로 운영 -> class당 jvm이 1대씩 할당된다
  • jvm은 class에 api를 제공

  • new(생성) --admitted--> ready : 프로세스 생성을 승인받음
  • ready or runnable --dispatch-->Running :
    • dispatch : 준비 상태에 있는 여러 프로세스 중 하나가 스케줄러에 의해 실행
  • running(실행) --interrupt-->ready, runnable : Timeout,
    • interrupt : 이벤트가 발생해서 현재 실행중인 프로레스(스레드)가 준비 상태로 전환되는 것
  • running(실행) ---->waiting :
    • 실행 중인 프로세스가 입출력/이벤트에 의해 대기해야 하는 경우
    • 입출력/이벤트가 끝날때가지 대기해야 하는 경우
  • waiting ----> ready :
    • 다시 준비 상태로 만들어서 스케줄러에 의해 선택될 수 있도록 상태 전환

Thread Method

  • interrupt()
    1. 스레드를 안전하게 종료시킬때 사용
    2. 스레드를 실행 도중 종료 시키고 싶을때 사용

0개의 댓글