[Java] JDBC 정리
·
Java
JDBC 개요JDBC 등장 배경일반적으로 애플리케이션이 데이터베이스와 통신하려면 다음 과정을 거친다커넥션 연결: TCP/IP를 사용하여 DB에 연결SQL 전달: 애플리케이션에서 SQL을 DB에 전송결과 응답: DB가 SQL을 실행하고 결과를 반환그러나, 데이터베이스마다 커넥션 방식, SQL 전달 방식, 응답 처리 방식이 달라 개발자는 매번 새로운 DB에 맞춰 코드를 변경해야 하는 문제가 있었다..=> 이를 해결하기 위해 JDBC(Java Database Connectivity)가 등장JDBC 표준 인터페이스JDBC는 자바에서 데이터베이스에 접속할 수 있도록 설계된 표준 API애플리케이션과 데이터베이스 사이의 의존성 역전을 적용한 것JDBC에서 제공하는 표준 인터페이스java.sql.Connection: ..
[Java] 소켓 통신과 네트워크 예외
·
Java
두 개의 호스트가 TCP/IP 프로토콜을 사용하여 서로 통신을 한다고 하자. 클라이언트와 서버 간의 데이터 통신을 위해서는 양쪽에 Socket이 열려있어야 한다. Socket은 서버와 연결되어 있는 연결점이라고 생각하면 된다. 자바에서는 다음과 같이 소켓을 통해 TCP 접속을 시도할 수 있다. 먼저 클라이언트에서 서버와 통신하기 위한 코드를 살펴보자.클라이언트 코드SocketSocket socket = new Socket("localhost", PORT);Socket 생성자의 매개변수로 호스트명과 포트번호를 전달한다.전달된 호스트명과 매핑되는 IP를 찾기 위해 Socket은 내부적으로 InetAddress를 사용한다InetAddress.getByName("호스트명")을 통해 호스트명과 매핑되는 IP 주소..
[Java] 제네릭(Generics)
·
Java
제네릭(Generics)이란제네릭(Generics): 클래스 내부에서 사용할 데이터 타입을 외부에서 지정하는 기법컴파일 시 타입 안정성을 보장하고, 타입 캐스팅을 줄여 코드의 가독성과 재사용성을 높이기 위한 기능Java 5에서 처음 도입ex) List list = new ArrayList();위 코드에서 꺾쇠() 괄호가 제네릭. 이를 '다이아몬드 연산자'라고 함.=> List 클래스 자료형의 타입은 Integer 타입으로 지정되어 정수형 데이터만 리스트에 적재하 수 있게 됨제네릭은 배열의 타입을 지정하듯이 리스트 자료형 같은 컬렉션 클래스나 메소드에서 사용할 내부 데이터 타입(type)을 파라미터(parameter) 주듯이 외부에서 지정하는 이른바 타입을 변수화 한 기능제네릭 타입 매개변수다이아몬드 연산..
[Java] 스레드 풀 & ExecutorService
·
Java
스레드를 직접 사용할 때의 문제점스레드 생성 시간으로 인한 성능 문제메모리 할당: 스레드는 자신만의 호출 스택을 가지고 있어야 하는데, 이는 곧 메모리 공간을 할당해주는 작업이다.운영체제 자원 사용: 스레드 생성 작업은 시스템 콜(system call)을 통해 처리된다. 즉, CPU와 메모리 리소스를 소모하는 작업이다.운영체제 스케줄러 설정: 새로운 스레드가 생성되면 운영체제의 스케줄러는 이 스레드를 관리하고 실행 순서를 조정해야 한다 → 오버헤드참고로 스레드 하나는 보통 1MB 이상의 메모리를 사용한다.⇒ 스레드 생성 작업은 상대적으로 무거우며, 어떤 작업 하나를 수행할 때마다 스레드를 각각 생성하고 실행한다면, 이 생성 비용 때문에, 이미 많은 시간이 소모될 것⇒ 생성한 스레드를 재사용할 필요가 있다..
[Java] 동시성 컬렉션
·
Java
동시성 컬렉션이 필요한 이유java.util 패키지에 소속되어 있는 컬렉션 프레임워크들은 스레드 세이프(thread-safe)하지 않다!⇒ 원자적인 연산처럼 느껴지는 메서드들의 대부분은 내부를 확인해보면 모두 여러개의 연산들로 이루어져 있으며 이들은 동시성 문제를 유발할 수 있다..ArrayList에 값을 추가하는 경우만 해도, 내부에 있는 배열에 데이터를 추가하고, size도 증가시키는 것과 같은 작업을 해야하며, size를 증가시키기 위한 size++ 연산 자체도 원자적이지 않다.⇒ 멀티스레드 상황에서 여러 스레드가 동시에 컬렉션에 접근하는 경우라면 절대 java.util 패키지가 제공하는 일반적인 컬렉션들은 사용하면 안된다! (물론 일부 예외도 있다) 이렇게 원자적이지 않은 연산을 멀티스레드 상황에..
[Java] CAS - 동기화와 원자적 연산
·
Java
원자적 연산소개컴퓨터 과학에서 사용하는 원자적 연산(atomic operation)의 의미는 해당 연산이 더 이상 나눌 수 없는 단위로 수행된다는 것을 의미한다. 즉, 원자적 연산은 중단되지 않고, 다른 연산과 간섭 없이 완전히 실행되거나 전혀 실행되지 않는 성질을 가지고 있다. 쉽게 이야기해서 멀티스레드 상황에서 다른 스레드의 간섭 없이 안전하게 처리되는 연산이라는 뜻이다. 다음과 같은 필드가 있을 떄,volatile int i = 0; i = 1은 둘로 쪼갤 수 없는 원자적 연산이다. 단 하나의 순서로 실행되기 때문이다. 하지만, 다음의 연산은 원자적 연산이 아니다.i = i + 1; 왜냐하면 이 연산은 다음 순서로 나누어 실행되기 때문이다.오른쪽에있는 i의 값을 읽는다. i 의값은 10이다.읽은 ..
[Java] 스레드 - 생산자 소비자 문제
·
Java
생산자 소비자 문제생산자 소비자 문제는 멀티스레드 프로그래밍에서 자주 등장하는 동시성 문제 중 하나로, 여러 스레드가 동시에 데이터를 생산하고 소비하는 상황을 다룬다.기본 개념생산자(Producer): 데이터를 생성하는 역할을 한다. 예를 들어, 파일에서 데이터를 읽어오거나 네트워크에서 데이터를 받아오는 스레드가 생산자 역할을 할 수 있다.소비자(Consumer): 생성된 데이터를 사용하는 역할을 한다. 예를 들어, 데이터를 처리하거나 저장하는 스레드가 소비자 역할을 한다.버퍼(Buffer): 생산자가 생성한 데이터를 일시적으로 저장하는 공간이다. 이 버퍼는 한정된 크기를 가지며, 생산자와 소비자가 이 버퍼를 통해 데이터를 주고받는다.문제 상황생산자가 너무 빠를 때: 버퍼가 가득 차서 더 이상 데이터를 ..
[Java] 스레드 동시성 문제
·
Java
메모리 가시성실제 메모리의 접근 방식CPU는 처리 성능을 개선하기 위해 중간에 캐시 메모리라는 것을 사용한다.각 스레드가 runFlag의 값을 사용하면 CPU는 이 값을 효율적으로 처리하기 위해 먼저 runFlag를 캐시 메모리에 불러온다.그리고 이후에는 캐시 메모리에 있는 runFlag를 사용하게 된다.즉, 각 스레드는 자신만의 고유한 캐싱된 데이터를 사용하고 있기 때문에, main 스레드에서 runFlag 값을 변경해도, work 스레드의 캐시 메모리는 값이 변경되지 않아서 데이터 정합성이 깨진다.핵심은 캐시 메모리의 runFlag 값만 변하고, 메인 메모리에 이 값이 즉시 반영되지 않는다는 것이다.캐시 메모리에 있는 runFlag의 값이 메인 메모리에 언제 반영될지는 알 수 없다.CPU 설계 방식과..
[Java] 스레드의 생성 / 실행 / 제어 / 생명 주기
·
Java
스레드 시작자바 메모리 구조 복습메서드 영역: 프로그램을 실행하는데 필요한 공통 데이터 관리. 프로그램의 모든 영역에서 공유클래스 정보: 클래스의 실행 코드(바이트 코드), 필드, 메서드와 생성자 코드 등 모든 실행 코드가 존재static 영역: static 변수 보관런타임 상수 풀: 프로그램을 실행하는데 필요한 공통 리터럴 상수 보관스택 영역: 각 스레드 별로 하나의 실행 스택 생성. 각 스택 프래임은 지역 변수, 중간 연산 결과, 메서드 호출 정보 등을 포함스택 프레임: 스택 영역에 쌓이는 네모 박스가 하나의 스택 프레임. 메서드를 호출할 때마다 하나의 스택 프레임이 쌓이고, 메서드가 종료되면 해당 스택 프레임이 제거됨힙 영역: 객체(인스턴스)와 배열이 생성되는 영역. 가비지 컬렉션이 이루어지는 주요..
[Java] Optional
·
Java
Optional 클래스java.util.Optional 클래스Optional 클래스는 Integer나 Double 클래스처럼 'T'타입의 객체를 포장해 주는 Wrapper classOptional 인스턴스는 모든 타입의 참조 변수를 저장할 수 있음.Optional 객체를 사용하면 예상치 못한 NullPointerException 예외를 제공되는 메소드로 간단히 회피할 수 있음. 복잡한 조건문 없이도 널(null) 값으로 인해 발생하는 예외를 처리할 수 있게 됨.Optional 객체 생성of() 메소드나 ofNullable() 메소드를 사용하여 Optional 객체를 생성of 메소드: null이 아닌 명시된 값을 가지는 Optional 객체를 반환. 만약, of() 메소드를 통해 생성된 Optional 객..