[Java Multi-Threading] 생산자 소비자 Queue 예제 연습해보기
·
Java
멀티 스레드 개발에 익숙해지는데 실전적인 상황에 대한 연습은 해보면 해볼 수록 도움이 된다. 실제로 메인 스레드에서 분리해서 비동기 작업을 하는 경우에 멀티 스레드를 활용해서 작업을 실행하는 경우는 많이 사용된다. 실제 개발 과제로 만날 법한 상황에 대한 시나리오를 한 번 마련해보고 이를 예제로 풀어보자. 문제 시작 멀티 스레드로 로그를 처리하는 시스템을 만든다고 하자. 여러 서비스로부터 로그를 앱이 수신하고, 모으다가 디스크에 일괄 저장하는 앱이다. 다음과 같은 요구사항들을 가져가보자. 여러 서비스들이 스레드로 로그 메세지를 생성해서 전달한다로그 메세지는 메세지 큐에 쌓이다가, 디스크에 저장을 처리하는 또다른 Writer 스레드로 인해 처리된다Writer 스레드는 큐에서 하나씩 꺼낸다, 이 때,..
[실전 Java 고급 1편] - 6. Executor Framework 에 대하여 2
·
Java
Thread Pool 과 Executor Framework 2 1. 우아한 종료 우아한 종료 (graceful shutdown) 자체는 SW에서 매우 중요한 개념이다. "기존에 진행중이던 작업을 완료한 이후 문제 없이 안정적으로 SW를 종료"하는 것을 말한다. 가령, 서버가 재기동되어야 할 때, 현재 처리중이던 요청이 있다면 마무리하고 종료해야 하는 것을 말한다. void shoutdown()새로운 작업을 받지 않고, 제출된 작업을 모두 완료한 후 종료한다. Non-Blocking 함수우리가 사용하던 close() 와 동일하다고 보면 된다. (24시간 뒤에 안되면 shutdownNow() 호출)List shutdownNow()긴급 중단. 실행 중인 작업들을 중단하고 대기중인 작업들은 반환된다. No..
[실전 Java 고급 1편] - 5. Executor Framework 에 대하여
·
Java
Thread Pool 과 Executor Framework 1. 스레드를 정말 직접 생성하며 사용할까? 스레드를 직접 생성하는 것은 자주 발생하진 않는다. 스레드는 단순 자바 객체를 생성하는 것과는 비교할 수 없는 매우 큰 작업이기 때문이다. 메모리 할당 → 물리 메모리 내에서 자신이 사용할 스택 공간 생성이 필요운영체제 자원 사용 → 스레드 생성은 커널 영역에서 이루어진다. 시스템 콜을 통해 처리되며 CPU 및 메모리 소모율이 높다운영체제 스케줄러 설정 → 운영체제가 관리할 스레드가 증가하며 순서 조정이 필요하다 만약 단순한 작업이라면, 오히려 스레드를 준비하는 과정이 더 커서 배보다 배꼽이 더 큰 상황일 수도 있다. 또한, 서버의 CPU 및 메모리는 한정되어 있기 때문에, 요청 당 스레드 할당..
[실전 Java 고급 1편] - 4. CAS와 동시성 컬렉션
·
Java
CAS, 동기화와 원자적 연산 1. 원자적 연산에 대하여 CS에서 원자적 연산이라 함은, 해당 연산이 더 이상 나눌 수 없는 단위로 수행된다는 것을 의미하며, 중단되지 않고 간섭 없이 완전히 실행되거나 전혀 실행되지 않는 연산이다. 즉, 다른 스레드의 간섭 없이 안전하게 처리되는 연산이라는 뜻이다. 가령, i = 1 은 둘로 쪼갤 수 없는 원자적 연산이다. 하지만, i = i+1 은 원자적 연산이 아니라, i 값을 읽고, 1을 더하고, 더한 값을 i에 대입하는 세가지 순서로 나뉘어진다. 이 모든 것은 CPU 입장에서이다! 원자적 연산이 아닌데 멀티 스레딩이 적용되는 상황에서 우리가 동기화 처리를 해왔던 것이다. 다음 상황을 살펴보자 public class V1BasicInteger implement..
[실전 Java 고급 1편] - 3. 생산자 소비자 문제 (BlockingQueue 만들기까지)
·
Java
생산자 소비자 문제 1 - Synchronized 심화 1. 소개 생산자 소비자 문제는 멀티 스레딩 세계에서 자주 등장하는 동시성 문제이다. 데이터 생산/소비하는 스레드가 동시에 많을 상황을 다룬다. 생산자는 데이터를 생산하는 스레드들을(파일에서 읽어오거나, 네트워크에서 받아옴) 말하고, 소비자는 이를 출력하거나, 저장하거나, Message Queue 로 활용하는 등 데이터를 소모하는 역할이다. 마지막으로 버퍼는 한정된 크기를 가지고, 데이터가 일시적으로 저장되는 공간이다. 생산자/소비자는 이 버퍼를 중심으로 데이터를 주고 받는다. 문제는 생산/소비 속도가 차이가 심해서, 한 쪽이 대기하는 상황에서 발생한다. 데이터가 생산 속도가 더 빠르면 버퍼에 더 이상 공간이 없으므로, 생산자 스레드는 대..
[실전 Java 고급 1편] - 2. 메모리 가시성과 동기화
·
Java
메모리 가시성  1. Volatile 에 대하여  public static void main(String[] args) { MyTask task = new MyTask(); Thread t = new Thread(task, "work"); log("runFlag = " + task.runFlag); // 시작은 당연히 True t.start(); ThreadUtils.sleep(1000); log("runFlag를 False 로 변경 시도 : work Thread 중지 예상"); task.runFlag = false; log("실제 runFlag 값 = " + task.runFlag); // main 스레드에서 조회시 False 로 출력됨 (내가 ..
[실전 Java 고급 1편] - 1. Thread 의 제어
·
Java
프로세스와 스레드 개요  1. 멀티태스킹과 멀티 프로세싱  * 멀티태스킹 - 하나의 CPU 코어가 Time Sharing 기법을 사용하여 동시에 여러 작업을 수행하는 능력* 스케줄링 - CPU 코어에 어떤 프로그램이 얼만큼 실행될지 결정하는 것, 운영체제가 여러가지 최적화를 사용* 멀티프로세싱 - CPU 코어가 둘 이상일 때, 한 컴퓨터 시스템에서 여러 작업을 동시에 처리하는 것  멀티프로세싱은 하드웨어 장비의 관점으로, HW 기반 성능 향상을 말한다. 멀티태스킹은 단일 CPU 코어가 여러 작업을 동시에 수행하는 것처럼 보이게 하는 것으로, SW 기반의 작업이다.   2. 프로세스와 스레드    프로그램은 실행하기 전까지 단순 파일이고, 실행되는 순간 운영체제 안에서 인스턴스가 되며 실행중인 프로그램을 ..
[Java] OOP, 객체 지향의 5대 원칙 (SOLID)
·
Java
Java 로 프로그램을 하게 될 경우, Java 의 언어적 특성인 객체지향 (OOP) 특성을 잘 반영하는 것이 중요합니다. 결국 모든 앱은 유지 보수 측면이 매우 중요한데, 이 OOP 측면을 잘 지키면, 유지 보수 및 관리에 큰 이점을 가져갈 수 있기 때문입니다. 이것이 어떻게 보면 Java 를 사용하는 이유라고 볼 수도 있을 것 같습니다.  객체 지향 설계에서 앱을 더욱 가독성 있고, 유연하고, 유지 보수 측면에서 유리하게 설계하기 위해서 제안되는 다섯가지 원칙을 SOLID 라고 합니다. Rober C. Martin 에 의해 제안된 이 다섯가지 원칙을 살펴보겠습니다.  굳이 다섯 포스트 만들면서 하나하나 까야할 내용은 아닌 것 같습니다. 차피 직접 설계해보시지 않으면 완전한 자신의 것이 되기는 힘들고,..