병렬성(parallelism)의 문제 1) CPU마다 갖는 캐시를 서로 다르기 때문에 동기화가 어렵다는 문제가 있음(서로 로컬 캐시 이기 때문)2) L3 캐시를 사용하더라도 사로 다른 코어가 동시에 접근할 수 없음(lock) - 보통의 경우 먼저 선점한 코어가 빠져나오기까지 block 됨. - 이럴 거면 멀티 코어를 쓰는 의미가 없어짐 위와 같이 비동기(순서가 서로 다른), 병렬성에 따른 문제가 있었고 이를 해결하기 위해 프로그래밍 언어 레벨에서 해결하려는 노력들(RxJava, 콜백)이 있었다. 이러한 노력에도 단점들이 있는데, 콜백을 사용할 경우 콜백 정의부가 메소드 내부 인자로 들어감에 따라 코드 depth가 커지고 가독성이 나빠질 수 있으며 RxJava를 사용할 때엔 항상 스트림을 사용..
컨셉 - JetBrains 사에서 만든 언어- JVM 기반 언어 - .java에서 컴파일된 .class 파일을 동일하게 코틀린에서도 사용 - 자바에서 소스파일을 .java로 사용하듯 코틀린에서 같은 레벨에 .kt 파일로 정의됨- 코틀린이 자바와 100% 호환될 수 있는 이유: 코틀린도 .class 파일로 컴파일되기 때문. 따라서 import를 통해 코틀린 소스코드 내에서 자바 라이브러리, 스프링 등을 참조할 수 있음(import 시 이미 컴파일된 class를 참조하기 때문)- 2016년 코틀린 1.0 릴리즈, 스프링 프레임워크 5.0부터 코틀린 공식 지원, gradle의 경우 Groovy에 더해 Kotlin DSL 지원- JetBrains 사에서 코틀린 기반의 백엔드 애플리케이션 프레임워크 ..
Netty에서 제공되는 I/O는 모두 Non-Blocking 기반이다. 예를 들어, Bootstrap에 대한 connect, bind 또는 writeAndFlush 등의 I/O 메소드는 모두 Non-blocking I/O 기반으로 동작한다. Non-Blocking I/O Non-Blocking I/O는 쓰레드가 실행 중에 I/O 연산을 마주했을 때 system call을 하고 바로 빠져나와(Non-Blocking I/O) 다음 작업을 처리하는 방식이다. 따라서 Non-blocking I/O기반의 작업은 I/O가 완료되기 전까지 다른 작업을 수행할 수 있다는 게 핵심이다. 이러한 개념에 비추어 봤을 때, I/O 시간이 오래걸리는 것에 대해서 Non-blocking을 기반으로 하는 것이 좋다. I/O 시간이..
최종 연산과 중간 연산 스트림이란 일련의 데이터의 흐름이다. 실질적으로는 스트림은 인스턴스로 존재하고 여러 개의 파이프를 통과함으로써 알련의 작업이 처리된다. 여기서 파이프는 메소드 호출을 통해 이루어진다. 최종 연산을 담당하는 파이프는 가장 마지막에 위치해야 한다. 최종 연산이 아닌 그 외 연산은 모두 중간 연산이라고 부른다. - 최종 연산(Terminal Operation) : 스트림을 연산하기 위한 파이프 중 가장 마지막의 연산을 담당하는 파이프 - 중간 연산(Intermediate Operation) : 최종 연산이 아닌 파이프에서 처리되는 연산들 예를 들어 홀수만 찾아내고 이들의 합을 구하는 연산이 있다고 가정하면 총 2가지 연산(홀수 찾기, 더하기)이 존재하고 이들 간의 순서는 홀수를 찾는 것..
이 글에서 말하는 Stream I/O는 일반적으로 자바에서 말하는, 필더링, 리덕션 등의 고차 함수를 이용하는 Stream과 다르다. I/O라는 용어가 붙었기 때문에 file, device, socket I/O 등 운영체제의 도움을 받아 처리되는 데이터의 입출력을 말하는 것이다. Stream I/O 추상적으로 Stream은 '데이터의 흐름'이다. 좀 더 이해를 쉽게 하자면 '데이터가 이동하는 통로'라고 생각해도 좋다. 자바에서 Stream(java.io)은 단방향 통신만을 지원하기 때문에 InputStream과 OutputStream을 따로 둘 수밖에 없었다. 또한 Stream은 Blocking I/O 만을 지원하기 때문에 모든 I/O 작업이 완료되기 전까지 자바 프로세스가 다른 작업을 수행할 수 없다...
디폴트 메소드 도입 자바 8부터 인터페이스의 기능이 개선되었다. 그중 하나가 인터페이스가 구현체를 가지게 된 것인데 이것이 인터페이스의 디폴트 메소드이다. 인터페이스는 모든 메소드가 추상 메소드로만 이루어진 클래스를 의미한다. 하지만 자바 8부터 디폴트메소드가 인터페이스에 들어갈 수 있게 되면서 추상 클래스와의 차이가 거의 없어졌다. 예시 default void say() { // 디폴트 메소드의 구현 몸체부 // 디폴트 메소드의 구현 몸체는 이를 구현하는 클래스가 아닌, // 인터페이스가 자체적으로 가지고 있음 } 디폴트 메소드를 사용하는 이유 - 어뎁터의 기능 사용 - 디폴트 메소드 등장으로 인해 static 메소드도 가질 수 있게 됨. - default, static 메소드들은 implements를..
Collection 인스턴스 동기화 - 2개 이상의 쓰레드가 컬렉션에 동시에 접근한다는 가정이 필요할 땐 동기화를 해주어야 한다. - 일반적인 대부분의 컬렉션들(ArrayList, HashMap 등)은 동기화가 되어있지 않다. 컬렉션 동기화 메소드 1) public static Set synchronizedSet(Set s) 2) public static List synchronizedList(List list) 3) public static Map synchronizedMap(Map m) 4) public static Collection synchronizedCollection(Collection c) - 위 메소드에서 동기화가 되어 있지 않은 컬렉션을 인자로 주면 동기화 기능이 추가된 컬렉션으로 반환..
쓰레드 생성 과정 1. Runnable 인터페이스를 구현한 인스턴스 생성 2. Thread 인스턴스 생성 3. start 메소드 호출 예제코드1 class Solution { final static ThreadLocal threadLocal = new ThreadLocal(); public static void main(String[] args) { Runnable task = () -> { threadLocal.set(1); int num1 = 10; int num2 = 20; String ctName = Thread.currentThread().getName(); System.out.println(MessageFormat.format("num1 + num2 = {0} from {1} and threa..
- Total
- Today
- Yesterday
- Kotlin
- kafka
- GitOps
- Non-Blocking
- Kubernetes
- jvm
- db
- 컨트롤러
- spring
- 우분투
- docker
- argocd
- ubuntu
- CICD
- Java
- go
- 쿠버네티스
- LFCS
- 코틀린
- Stream
- ci/cd
- rolling update
- K8s
- RDB
- golang
- github actions
- Controller
- 카프카
- Linux
- container
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |