개요스레드 생성 과정은 간략하게 아래와 같은 과정이 이루어진다.메모리 할당 -> 시스템 콜(커널 모드 전환) -> 운영체제에서 스레드 생성 -> 운영체제 스케쥴러 관리 -> 작업이 완료되면 스레드 종료스레드 생성 과정은 너무 무겁다.또한 서버의 자원은 한정되어 있기에, 스레드를 무한하게 생성할 수도 없다. 스레드 풀을 이용하면 스레드들을 미리 만들어서 보관해놓고 생성 과정을 일부 생략하여 작업을 빠르게 진행시킬 수 있으며, 최대 스레드 수를 설정하여 서버의 자원을 초과하지 않도록 할 수 있다. Executor 프레임워크자바에서는 Executor 프레임워크를 통해 스레드 풀 관리를 간단하고 효율적으로 처리할 수 있다. public interface ExecutorService extends Execut..
개요동기와 비동기, 블로킹과 논블로킹, 많이 들어본 용어이지만 가끔씩은 헷갈린다.어떤 기준으로 나뉘었는지 알아보고 이 두 종류 조합도 알아보자. 동기와 비동기동기와 비동기를 나누는 기준은 '작업들을 순차적으로 수행하는지'에 대한 관점이다.동기는 작업을 순차적으로 수행하고, 비동기는 작업들이 순서에 상관없이 수행된다. 블로킹과 논블로킹블로킹과 논블로킹을 나누는 기준은 '작업의 제어권을 어떻게 처리하느냐'에 대한 관점이다.다른 말로 '현재 진행중인 작업이 block 되느냐 안되느냐'이다.A 작업이 B 작업을 호출할 때 제어권을 A가 B에게 넘기게 되어서 A 작업이 중단된다면, 해당 상황은 블로킹이다.반대로 A 작업이 B 작업을 호출해도 제어권을 A 작업이 그대로 갖고 있어 작업이 중단되지 않는다면, 해당..
개요Spring data repository의 saveAll() 메서드는 그 이름 덕분인지, 여러 개의 데이터들을 하나의 쿼리로 처리할 것만 같다. 하지만 실제 적용해보니 예상과는 다르게 동작하는 부분들이 있었기에 기록으로 남겨보려 한다. 문제customerCreditTransactionRepository.saveAll(creditTransactions);100개 정도 되는 데이터를 한 번에 저장할 일이 있었다. 나는 위 코드처럼 saveAll()을 통해서 하나의 쿼리로 처리할 수 있을 줄 알았다. 하지만 실제 동작은 데이터를 각각의 INSERT 쿼리로 처리하는 것 아닌가... 원인왜 saveAll() 메서드가 한 번에 쿼리로 처리하지 못하는 것일까? 원인은 JPA의 기본키 생성 전략이였다. @Ent..
동기화란스레드 개념의 도입으로 하나의 프로세스에서 여러 스레드들이 동시에 작업을 처리할 수 있게 되었지만, 스레드들이 프로세스의 자원을 공유하며 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("주사위 = " + ..
개요데이터 삭제 정책이 soft delete라면, 데이터 조회 시 delete 상태 여부를 확인하는 조건을 일일이 넣어주어야 할 것이다.@SQLRestriction 어노테이션을 통해 SQL의 where절에 delete 상태 여부를 체크하는 조건을 넣는 방법을 소개하려 한다. 문제코드를 살펴보자. 먼제 Hospital 엔티티이다.@Entity@Table(name = "hospitals")class Hospital( @Id @GeneratedValue(strategy = GenerationType.IDENTITY) val id: Long? = null, val name: String, ... //삭제가 된 상태라면, 해당 필드에 값 존재 var deletedAt..