JDK 동적 프록시와 CGLIB를 사용해서 AOP 프록시를 만드는 방법에는 각각 장단점이 있습니다. JDK 동적 프록시는 인터페이스가 필수이고, 인터페이스를 기반으로 프록시를 생성합니다. 반면에 CGLIB는 구체 클래스를 기반으로 프록시를 생성합니다.만약 인터페이스가 없고 구체 클래스만 있는 경우에는 CGLIB를 사용해야 합니다. 그런데 인터페이스가 있는 경우에는 JDK 동적 프록시나 CGLIB 둘중에 하나를 선택할 수 있습니다.스프링에서는 프록시를 만들때 제공하는 ProxyFactory에 proxyTargetClass 옵션에 따라 둘중 하나를 선택해서 프록시를 만들 수 있습니다.proxyTargetClass=false: JDK 동적 프록시를 사용해서 인터페이스 기반 프록시 생성proxyTargetCla..
생산자 소비자 문제를 실무에서 사용할 때는, 결국 소비자가 처리할 수 없을 정도로 생산 요청이 가득 차면 어떻게 할지를 정해야 합니다. 개발자가 인지할 수 있게 로그도 남겨야 하고, 사용자에게 현재 시스템에 문제가 있다고 알리는 것도 필요할텐데, 이런 것을 위해 바로 예외 정책이 필요합니다.ThreadPoolExecutor에 작업을 요청할 때, 큐도 가득차고, 초과 스레드도 더는 할당할 수 없다면 작업을 거절합니다.이를 위해 작업을 거절하는 다양한 정책을 제공하고 있습니다.AbortPolicy: 새로운 작업을 제출할 때 RejectedExecutionException을 발생시킨다. 기본 정책이다.DiscardPolicy: 새로운 작업을 조용히 버린다.CallerRunsPolicy: 새로운 작업을 제출한 ..
현재 고객의 주문을 처리하는 서버를 운영중이고, 서버 기능을 업데이트를 위해서 서버를 재시작해야 한다고 가정해보겠습니다.이때 서버 애플리케이션이 고객의 주문을 처리하고 있는 도중에 갑자기 재시작 된다면, 해당 고객의 주문이 제대로 진행 되지 못할 것입니다.가장 이상적인 방향은 새로운 주문 요청은 막고, 이미 진행중인 주문은 모두 완료한 다음에 서버를 재시작 하는 것이 가장 좋을 것입니다. 이처럼 서비스를 안정적으로 종료하는 것도 매우 중요합니다.이렇게 문제 없이 우아하게 종료하는 방식을 graceful shutdown이라 합니다. 이런 관점에서 ExecutorService의 종료에 대해서 알아보겠습니다.ExecutorService 종료 메서드ExecutorService에는 종료와 관련된 다양한 메서드가 ..
멀티 스레드를 이용하여 프로그래밍을 하다보면, CPU Cache Memory와 Main Memory간의 일치하지 않는 데이터로 인해 문제가 발생하기도 합니다. 이때 이를 방지하기 위해 volatile 키워드를 사용할 수 있습니다.이번에는 volatile과 메모리 가시성을 이해하고자, 간단한 예제를 통해 알아보겠습니다.메모리 가시성public class VolatileFlagMain { public static void main(String[] args) { MyTask task = new MyTask(); Thread t = new Thread(task, "work"); log("runFlag = " + task.runFlag); t.start();..
저번 포스팅에 이어 자바의 Future에 대해 알아보겠습니다.Future - 취소이번에는 아래 코드를 통해 cancel()이 어떻게 동작하는지 알아보겠습니다.public class FutureCancelMain { private static boolean mayInterruptIfRunning = true; // 변경 // private static boolean mayInterruptIfRunning = false; // 변경 public static void main(String[] args) { ExecutorService es = Executors.newFixedThreadPool(1); Future future = es.submit(new MyTask()..
저번 포스팅에 이어 자바의 Future에 대해 알아보겠습니다.이번에는 1~100까지 더하는 경우를 스레드를 사용해서 1부터 50, 51부터 100으로 나누어 처리하는 예제를 작성하였습니다.스레드1: 1~50까지 더함 스레드2: 51~100까지 더함SumTask - Runnable먼저 ExecutorService없이 Runnable과 순수 스레드로 수행해보겠습니다.public class SumTaskMainV1 { public static void main(String[] args) throws InterruptedException { SumTask task1 = new SumTask(1, 50); SumTask task2 = new SumTask(51, 100); ..
이번에는 Executor 프레임워크 포스팅에 이어 자바의 Future에 대해 알아보겠습니다.Runnable과 Callable 비교Runnable은 다음과 같습니다.package java.lang;public interface Runnable { void run();}Runnable의 run()은 반환 타입이 void이다. 따라서 값을 반환할 수 없다.예외가 선언되어 있지 않다. 따라서 해당 인터페이스를 구현하는 모든 메서드는 체크 예외를 던질 수 없다. 참고로 자식은 부모의 예외 범위를 넘어설 수 없다. 부모에 예외가 선언되어 있지 않으므로 예외를 던질 수 없다.물론 런타임(비체크)예외는 제외다.Callable은 다음과 같습니다.package java.util.concurrent;public int..
Executor 프레임워크에 대해 알아보기 전에 "쓰레드를 직접 사용할 때의 문제점"에 대한 내용은 여기에서 살펴보실 수 있습니다. 자바의 Executor 프레임워크는 멀티스레딩 및 병렬 처리를 쉽게 사용할 수 있도록 돕는 기능의 모음입니다. 이 프레임워크는 작업 실행의 관리 및 스레드 풀 관리를 효율적으로 처리해서 개발자가 직접 스레드를 생성하고 관리하는 복잡함을 줄여줍니다. Executor 프레임워크의 주요 구성 요소Executor 인터페이스package java.util.concurrent;public interface Executor { void execute(Runnable command);}가장 단순한 작업 실행 인터페이스로, execute(Runnable command) 메서드 하나를 ..
실무에서 스레드를 직접 생성해서 사용하면 다음과 같은 3가지 문제가 있습니다.스레드 생성 시간으로 인한 성능 문제스레드 관리 문제Runnable 인터페이스의 불편함1. 스레드 생성 비용으로 인한 성능 문제스레드를 사용하려면 먼저 스레드를 생성해야 합니다. 그런데 스레드는 다음과 같은 이유로 매우 무겁습니다.메모리 할당: 각 스레드는 자신만의 호출 스택(call stack)을 가지고 있어야 한다. 이 호출 스택은 스레드가 실행되는 동안 사용하는 메모리 공간이다. 따라서 스레드를 생성할 때는 이 호출 스택을 위한 메모리를 할당해야 한다. 운영체제 자원 사용: 스레드를 생성하는 작업은 운영체제 커널 수준에서 이루어지며, 시스템 콜(system call)을 통해 처리된다. 이는 CPU와 메모리 리소스를 소모하는..
동시성 컬렉션이 필요한 이유에 대해서는 여기에서 확인하실 수 있습니다.자바가 제공하는 java.util 패키지에 있는 컬렉션 프레임워크들은 대부분 스레드 안전(Thread Safe)하지 않습니다.우리가 일반적으로 사용하는 ArrayList, LinkedList, HashSet, HashMap 등 수 많은 기본 자료 구조들은 내 부에서 수 많은 연산들이 함께 사용됩니다. 배열에 데이터를 추가하고 사이즈를 변경하고, 배열을 새로 만들어서 배열의 크기도 늘리고, 노드를 만들어서 링크에 연결하는 등 수 많은 복잡한 연산이 함께 사용됩니다.그렇다면 처음부터 모든 자료 구조에 synchronized를 사용해서 동기화를 해두면 어떨까요?synchronized, Lock, CAS 등 모든 방식은 정도의 차이는 있지만 ..
- Total
- Today
- Yesterday
- Algorithm
- 코틀린
- 자료구조
- 김영한
- MySQL
- 자바
- Spring
- 북클럽
- spring boot
- 알고리즘
- 스프링
- 파이썬
- 노마드코더
- 데이터베이스
- 문자열
- 백준
- 릿코드
- leetcode
- 그리디
- webflux
- kotlin
- mysql 8.0
- 인프런
- 스프링부트
- 정렬
- 코테
- Real MySQL
- 구현
- 스프링 부트
- Java
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | ||||||
| 2 | 3 | 4 | 5 | 6 | 7 | 8 |
| 9 | 10 | 11 | 12 | 13 | 14 | 15 |
| 16 | 17 | 18 | 19 | 20 | 21 | 22 |
| 23 | 24 | 25 | 26 | 27 | 28 | 29 |
| 30 |