애너테이션

  • 자바 소스 코드에 추가하여 사용할 수 있는 메타데이터의 일종
    • 메타데이터 - 데이터에 대한 데이터, 즉 데이터에 대해 설명이나 정보를 제공하기 위한 목적의 데이터
@RequiredArgsConstructor
public class PaymentRepositoryImpl implements PaymentRepositoryCustom {

    private final JPAQueryFactory queryFactory;

	// @Override는 해당 애너테이션이 붙은 메서드가 오버라이드 메서드임을 알려주는 애너테이션이다.
    @Override
    public Page<Payment> findByNameContains(String word, Pageable pageable) {
        List<Payment> payments = queryFactory.selectFrom(payment)
                .leftJoin(payment.student, student).fetchJoin()
                .where(searchCondition(word))
                .limit(pageable.getPageSize())
                .offset(pageable.getOffset())
                .orderBy(payment.id.desc())
                .fetch();

        int size = queryFactory.selectFrom(payment)
                .where(searchCondition(word))
                .fetch()
                .size();

        return PageableExecutionUtils.getPage(payments, pageable, () -> size);
    }
}

 

메타 애너테이션

  • 애너테이션을 정의하는데 사용되는 애너테이션. 애너테이션을 정의할 때에만 사용할 수 있다.

@Retention

  • 애너테이션이 유지되는 생명주기를 설정하는 메타 애너테이션
    • SOURCE
      • 소스 코드에서만 유지. 컴파일 시점에 제거됨
    • CLASS
      • 컴파일된 .class 파일에 애너테이션을 유지시킴. 런타임 시점에 제거됨
      • SOURCE 와 마찬가지로 런타임 시점에는 결국 제거된 상태지만 소스 코드 없이 .class 파일만 제공되는 상황에서 애너테이션 정보를 제공하기 위해서 사용됨 (ex - jar 파일의 .class)
    • RUNTIME
      • 런타임 시점까지 애너테이션을 유지시킴
@Retention(RetentionPolicy.SOURCE)
@Retention(RetentionPolicy.CLASS)
@Retention(RetentionPolicy.RUNTIME)

애너테이션의 Retention 설정값이 SOURCE 의 경우 컴파일 후 바이트코드에서는 제거된다.

 

@Target

  • 애너테이션을 적용할 수 있는 유형을 설정하는 메타 애너테이션
  • TYPE, FIELD, METHOD, PARAMETER 등 다양한 유형을 지정할 수 있다.
@Target(ElementType.METHOD)
@Target(ElementType.PARAMETER)

 

@Inherited

  • @Inherited 이 적용된 애너테이션을 사용한 클래스를 상속한 서브클래스는 애너테이션 정보까지 상속받도록 하는 메타 애너테이션

'Java' 카테고리의 다른 글

Thread의 동기화 처리  (0) 2022.09.04
Demon Thread  (0) 2022.09.04
Thread 의 동시성과 병렬성  (0) 2022.09.01
JVM - Java Virtual Machine  (0) 2022.08.30
자바 소스 코드의 실행 과정  (0) 2022.08.30

동기화

  • 이전 작업이 완전히 완료된 후 다른 작업을 수행하는 것.
    • 반대로 이전 작업의 완료 여부와 상관없이 바로 다른 작업 명령을 수행하는 것을 '비동기화' 라고 한다.

 

멀티 쓰레드 환경에서의 비동기

class TestClass {
    int data = 3;

    void print(Thread thread) {
        System.out.println(thread.getName() + " : " + data);
        data += 1;
    }
}


@Test
@DisplayName("쓰레드 비동기 테스트")
void testThreadAsync() throws InterruptedException {
    TestClass testClass = new TestClass();
    Thread thread1 = new Thread(() -> testClass.print(Thread.currentThread()));
    thread1.setName("thread1");
    Thread thread2 = new Thread(() -> testClass.print(Thread.currentThread()));
    thread2.setName("thread2");
    Thread thread3 = new Thread(() -> testClass.print(Thread.currentThread()));
    thread3.setName("thread3");
    Thread thread4 = new Thread(() -> testClass.print(Thread.currentThread()));
    thread4.setName("thread4");

    // 실행 순서가 보장되지 않음
    thread1.start();
    thread2.start();
    thread3.start();
    thread4.start();

    Thread.sleep(2000);
    System.out.println("최종결과 : " + testClass.data);
}

  • 기본적으로 멀티 쓰레드 환경에서는 비동기적으로 작업을 수행하지만 이는 특정 상태값을 공유하는 작업에서 의도치않은 문제를 야기할 수 있으므로 주의해야한다. 때문에 웹 어플리케이션같은 멀티 쓰레드 환경에서는 서로 다른 요청을 담당하는 여러 쓰레드가 같은 상태값을 공유함으로서 발생할 수 있는 문제를 방지하기 위해 기본적으로 무상태성을 권장한다.

 

멀티쓰레드 환경에서의 동기화

class SyncClass {
    int data = 3;
    Object lock = new Object();

    // printA 와 printB 는 같은 this 객체의 Lock 을 사용하므로 동시에 진행될 수 없다.
    synchronized void printA(Thread thread) {
        System.out.println(thread.getName() + " : " + data);
        data += 1;
    }
    synchronized void printB(Thread thread) {
        System.out.println(thread.getName() + " : " + data);
        data += 1;
    }

    // callA 와 callB 내부의 동기화 블록은 같은 객체의 Lock 을 사용하므로 동시에 진행될 수 없다.
    void callA(Thread thread) {
        synchronized (lock) {
            System.out.println(thread.getName() + " : " + data);
            data += 1;
        }
    }
    void callB(Thread thread) {
        synchronized (lock) {
            System.out.println(thread.getName() + " : " + data);
            data += 1;
        }
    }
    
    // printA 와 callA 내부의 동기화 블록은 다른 객체의 Lock을 사용하므로 동시에 진행 가능
}
  • 메서드를 동기화할 때는 동기화하고자 하는 메서드의 리턴 타입 앞에 synchronized 키워드를 붙여준다.
  • 일정 영역을 블록으로 동기화할 때에는 synchronized(object) {} 블록으로 감싸준다.
    • 메서드 전체를 동기화하지 않고 메서드 내부의 필요한 부분만 한정해서 동기화를 적용할 때 동기화 블록을 사용한다.
  • 객체마다 하나의 Lock 을 보유하고 있으며 해당 Lock 이 필요한 동기화 메서드 혹은 동기화 블록을 처리하는 쓰레드는 해당 Lock 을 가지고 작업을 처리하며 Lock 을 반납하기 전까지는 해당 Lock 이 필요한 다른 쓰레드들은 Lock 이 반납될 때까지 대기하게 된다.

 

'Java' 카테고리의 다른 글

애너테이션  (0) 2022.09.06
Demon Thread  (0) 2022.09.04
Thread 의 동시성과 병렬성  (0) 2022.09.01
JVM - Java Virtual Machine  (0) 2022.08.30
자바 소스 코드의 실행 과정  (0) 2022.08.30

Demon Thread

  • 프로세스의 모든 일반 쓰레드가 종료될 때 남은 작업에 상관없이 같이 종료되는 쓰레드
  • 가비지 컬렉터, 자동 저장 등 프로그램 종료 시점에 맞춰 같이 종료되어야 하는 작업에 사용됨

 

public static void main(String[] args) {
    Thread commonThread = new Thread(() -> {
        String threadName = Thread.currentThread().getName();
        IntStream.range(0, 3).forEach(idx -> execute(threadName));
        System.out.println(threadName + " 종료");
    });
    commonThread.setName("commonThread");

    Thread demonThread = new Thread(() -> {
        String threadName = Thread.currentThread().getName();
        IntStream.range(0, 5).forEach(idx -> execute(threadName));
        System.out.println(threadName + " 종료");
    });
    demonThread.setDaemon(true);
    demonThread.setName("demonThread");

    try {
        commonThread.start();       // 일반 쓰레드 실행

        Thread.sleep(2000);     	// 1초 뒤 데몬 쓰레드 실행
        demonThread.start();
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }
    System.out.println("mainThread 종료");
}


public static void execute(String threadName) {
    System.out.println(threadName + " 실행");
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        throw new RuntimeException(e);
    }
}

'Java' 카테고리의 다른 글

애너테이션  (0) 2022.09.06
Thread의 동기화 처리  (0) 2022.09.04
Thread 의 동시성과 병렬성  (0) 2022.09.01
JVM - Java Virtual Machine  (0) 2022.08.30
자바 소스 코드의 실행 과정  (0) 2022.08.30

프로세스와 쓰레드

프로세스

  • 메모리 상에 로딩된 프로그램

쓰레드

  • 프로세스 내에서 실행되는 작업 단위
  • 하나의 프로세스 내에서 여러 쓰레드가 동시에 실행될 수 있다.
  • 프로세스는 최소 하나 이상의 쓰레드로 실행되며 자바의 경우 실행 시점에 main 쓰레드를 생성하여 작업을 실행한다.

 

쓰레드의 동시성

쓰레드의 동시성은 동시에 실행되는 것이 아닌 동시에 실행되는 것처럼 보이게하는 현상이다.

  • 쓰레드를 실행하는 주체는 CPU 의 코어로서 코어의 수가 쓰레드의 수보다 작을 경우 코어는 쓰레드를 번갈아가면서 실행된다. 이 때, 번갈아가면서 실행되는 주기는 사람이 인지할 수 없을 정도로 매우 짧아 사용자는 마치 동시에 실행되는 것처럼 느낀다. 이를 쓰레드의 동시성이라고 한다.

 

쓰레드의 병렬성

  • CPU 의 코어 수가 쓰레드의 수 이상일 때 각각의 코어는 하나의 쓰레드를 담당하여 실행, 즉 병렬적으로 처리한다.

'Java' 카테고리의 다른 글

애너테이션  (0) 2022.09.06
Thread의 동기화 처리  (0) 2022.09.04
Demon Thread  (0) 2022.09.04
JVM - Java Virtual Machine  (0) 2022.08.30
자바 소스 코드의 실행 과정  (0) 2022.08.30

JVM

  • 자바 가상 머신
  • 자바 바이트 코드를 OS에 맞는 바이너리 코드로 컴파일하여 실행
    • 자바는 플랫폼 독립적이지만 바이트 코드를 컴파일하는 JVM은 플랫폼 종속적이다.

 

JVM 의 구조

ClassLoader

  • .class 파일의 바이트 코드를 읽고 메모리에 저장한다.
  • 로딩, 링크, 초기화 순으로 진행하여 메모리의 각 영역에 데이터를 저장

 

Memory

Method 영역

  • 클래스 수준의 정보를 저장
    • 클래스 이름, 부모 클래스 이름, 메소드, 변수
    • 공유 자원으로서 쓰레드에 상관없이 사용 가능한 자원

Heap 영역

  • 객체를 저장하며 Method 영역의 자원과 마찬가지로 공유 자원이다.

Stack 영역

  • 쓰레드마다 런타임 스택을 생성하고 그 안에 메서드 호출마다 스택 프레임을 쌓는다. 쓰레드가 종료되면 런타임 스택도 제거된다.

PC Register

  • 쓰레드마다 쓰레드 내 현재 실행할 위치를 가리키는 포인터가 생성된다.

 

Execution Engine

Interpreter

  • 바이트 코드를 한 줄씩 바이너리 코드로 해석하여 실행

JIT Compiler 

  • 인터프리터의 효율을 높이기 위해 작동하는 컴파일러
  • 인터프리터가 반복되는 코드를 발견하면 해당 코드들을 모두 네이티브 코드로 컴파일한다.
    • 네이티브 코드로 컴파일된 코드는 인터프리터가 더 이상 해석하지 않고 바로 실행하여 속도가 향상된다.

Gavage Collector

  • 더 이상 참조되지 않는 객체를 모아서 메모리를 해제한다.

'Java' 카테고리의 다른 글

애너테이션  (0) 2022.09.06
Thread의 동기화 처리  (0) 2022.09.04
Demon Thread  (0) 2022.09.04
Thread 의 동시성과 병렬성  (0) 2022.09.01
자바 소스 코드의 실행 과정  (0) 2022.08.30

자바 소스 코드의 실행 과정

    1. 소스 파일 작성
      • 일반적으로 IDE 를 통해 작성한다.
    2. 바이트 코드 생성
      • 작성한 소스 파일을 컴파일하면 JVM 이 이해할 수 있는 바이트 코드(.class)가 생성된다.
      • eclipse, IntelliJ 등의 IDE 를 통해 소스 파일을 작성하는 경우에는 작성한 소스 파일을 저장할 때 자동으로 컴파일하여 바이트 코드를 생성한다.
    3. 바이트 코드 실행
      • JVM 은 바이트 코드를 읽고 메모리에 저장한다.
    4. 프로그램 실행
      • JVM 은 바이트 코드를 컴퓨터가 이해할 수 있는 바이너리 코드로 컴파일하여 실행한다. 이 때, main() 메서드가 가장 먼저 실행된다.

'Java' 카테고리의 다른 글

애너테이션  (0) 2022.09.06
Thread의 동기화 처리  (0) 2022.09.04
Demon Thread  (0) 2022.09.04
Thread 의 동시성과 병렬성  (0) 2022.09.01
JVM - Java Virtual Machine  (0) 2022.08.30

+ Recent posts