개요 - 기존 스레드의 한계Java의 전통적인 동시성 모델은 Thread per Request 모델로 요청에 대해 하나의 스레드를 할당한다. 해당 요청 처리가 끝날 때 까지 스레드가 점유된다. 문제는 JVM의 스레드(Platform Thread)는 OS 스레드와 1:1로 매핑되며, 스레드 당 메모리를 1~2MB 점유하므로 비용이 비싸다.서버의 자원은 한정되어 있기에 요청이 늘어난다고 해도, 수천 개 이상의 스레드를 생성하기에는 한계가 있다.또한 JVM의 스레드는 I/O 블로킹이 발생하면, 작업이 완료될 때까지 다른 요청을 처리할 수 없다. 동시 요청이 스레드 풀 크기를 초과하게 되면 나머지 요청은 대기할 수 밖에 없고 병목이 될 수 있다. Virtual Thread는 이러한 한계를 극복하고 처리량을 늘릴..
개요자바는 스레드를 통해 작업들을 병렬적으로 처리할 수 있다.하지만 Runnable 인터페이스를 통해 작업을 제출하게 되면, 반환값을 받을 수 없다는 단점이 있다.Executor 프레임워크는 이러한 문제를 해결하기 위해 Callable과 Future라는 인터페이스를 도입했다. 이전 글에 이어지는 내용이다. Runnable vs Callablepublic interface Runnable { void run();}Runnable 인터페이스는 반환 값이 없으며, 예외를 던질 수도 없다. public interface Callable { V call() throws Exception;}Callable 인터페이스는 값을 반환할 수 있으며, 예외를 던질 수 있다. Callable과 Future 사용class ..
개요스레드 생성 과정은 간략하게 아래와 같은 과정이 이루어진다.메모리 할당 -> 시스템 콜(커널 모드 전환) -> 운영체제에서 스레드 생성 -> 운영체제 스케쥴러 관리 -> 작업이 완료되면 스레드 종료스레드 생성 과정은 너무 무겁다.또한 서버의 자원은 한정되어 있기에, 스레드를 무한하게 생성할 수도 없다. 스레드 풀을 이용하면 스레드들을 미리 만들어서 보관해놓고 생성 과정을 일부 생략하여 작업을 빠르게 진행시킬 수 있으며, 최대 스레드 수를 설정하여 서버의 자원을 초과하지 않도록 할 수 있다. Executor 프레임워크자바에서는 Executor 프레임워크를 통해 스레드 풀 관리를 간단하고 효율적으로 처리할 수 있다. public interface ExecutorService extends Execut..
동기화란스레드 개념의 도입으로 하나의 프로세스에서 여러 스레드들이 동시에 작업을 처리할 수 있게 되었지만, 스레드들이 프로세스의 자원을 공유하며 Race Condition이나 데이터 불일치와 같은 동시성 문제들이 발생하게 되었다.여러 스레드가 접근할 때 동시성 문제가 발생할 수 있는 공유 자원을 임계 영역이라 하며, 동시성 문제가 발생하지 않으려면 임계 영역에 하나의 스레드만 접근할 수 있도록 해야한다. 스레드 간의 수행 시기를 맞추어 동시성 문제를 예방하는 것을 동기화라고 하며,자바에서도 멀티 스레드 상황에서 동시성 문제를 해결할 수 있는 여러 동기화 방법들을 제공한다. synchronized의 단점synchronized는 자바에서 동기화를 위한 가장 대표적인 키워드이다.자바에서 모든 객체는 모니터 ..
자바 스레드 생명 주기자바 스레드의 생명 주기는 시작부터 시작하여 실행, 일시 중지, 종료의 상태를 갖고 있다. 1. New - 스레드가 생성되고 아직 시작되지 않은 상태2. Runnable - 실행될 준비가 됐거나, 실제로 실행 중인 상태3. Blocked - 동기화 락을 기다리는 상태, synchronized에서만 사용하는 특별한 스레드 대기 상태4. Waiting - 다른 스레드의 작업이 완료되기를 무기한 기다리는 상태5. Timed Waiting - 스레드가 일정 시간 동안 대기하는 상태6. Terminated - 스레드의 실행이 완료된 상태 join - 다른 스레드의 작업 대기class SumTask implements Runnable { int startValue; int endV..
개요Stream은 중간 연산을 거친 데이터들을 collect 최종 연산을 통해 다양한 컬렉션으로 반환할 수 있다. 구조public interface Stream extends BaseStream> { .. //Collector 인터페이스를 통해 최종 연산 반환 타입 지정 R collect(Collector collector); ..}collect 연산은 Collector 인터페이스을 매개변수로 받아서 알맞은 컬렉션 형태로 반환한다. 자바에서 Collectors 클래스를 통해 Collector 인터페이스의 대부분 기능을 구현해 놓았다. Collectors 클래스에서 어떤 기능들로 어떤 타입들을 반환하는지 알아보자. List 반환//수정 가능List list = Stream...
Stream이란?Java 8부터 도입된 기능으로 데이터 흐름을 추상화해서 다루는 도구이다. 컬렉션 데이터를 함수형 프로그래밍 방식으로 처리할 수 있게 해준다. Stream 연산Stream 연산은 중간 연산과 최종 연산으로 나뉜다. List numbers = List.of(1,2,3,4)int sum = numbers.stream() .filter(n -> n % 2 == 0) // 중간 연산 -> 짝수 필터링 후 Stream 반환 .map(n -> n * 2) // 중간 연산 -> 두 배 변환 후 Stream 반환 .sum(); // 최종 연산 -> 합계 반환중간 연산은 Stream을 반환하여 중간 연산을 통해 체이닝이 가능하다. 최종..
메서드 참조란?이미 정의된 메서드를 그대로 참조하여 람다 표현식을 더 간결하게 작성하는 문법이다.즉, 람다가 단순히 이미 정의된 어떤 메서드를 호출하는 경우, 이를 축약해준다. 람다와 관련된 포스팅은 해당 글을 참고하면 좋을 것 같다. 람다 -> 메서드 참조Function function = s -> s.length();매개변수로 문자열이 들어오면 문자열의 길이를 반환해주는 람다식이다. Function function = String::length;위 람다식을 변환한 메서드 참조 형태이다.'::' 연산자를 사용해 메서드 참조를 나타 낼 수 있다. 메서드 참조에서는 컴파일러가 시그니처(매개변수, 타입)을 바탕으로 메서드 참조와 연결해주기 때문에, 명시적으로 매개변수를 작성하지 않아도 자동으로 추론되어 호..
개요메서드 파라미터에 값이 아닌 어떠한 로직을 넘기고 싶을 경우가 있다면, 어떻게 해야 할까? 인터페이스 구현 후, 구현한 클래스 넘기기public class ExMain { public static void hello(Procedure procedure) { //4. 메서드 실행 procedure.run(); } //1. 인터페이스 구현 static class Dice implements Procedure { @Override public void run() { int randomValue = new Random().nextInt(6) + 1; System.out.println("주사위 = " + ..