멀티스레드 (Multi-Thread) 개념 실행되지 않은 프로그램을 실행하게 되면 주기억장치에 해당 프로그램이 로딩되고 동작할 수 있는 상태인 '프로세스' 로 바뀝니다. 이러한 동적인 상태의 프로그램을 프로세스라고 하고 프로세스 내의 일련의 작업 단위 하나를 '스레드'라고 표현합니다. 어떤 프로세스든 기본적으로 하나의 메인 스레드가 존재 합니다. 메인 스레드를 중심으로 코드에 따라서 큰 흐름이 진행되는데 프로그램의 성질에 따라서 이러한 스레드가 여러 개 필요할 수 있습니다. 예를 들면 게임이나 웹 서비스 환경에서는 들어오는 요청 수가 동시적이면서 많을 수 있기 때문에 스레드 하나로 전부 처리한다면 간단한 요청에도 많은 시간이 걸릴껍니다. 그래서 Java는 이러한 환경에서 동시다발 적으로 들어오는 요청을 ..
이상현상이란? DB에서 이상현상이란 테이블 설계를 적절하게 하지 못한 경우 야기할 수 있는 문제들을 의미합니다. 관계형 데이터베이스는 릴레이션 간 관계를 설정함으로써 데이터의 무결성을 지키고 중복된 데이터들이 나오지 않도록 합니다. 하지만 어떤 서비스를 만들기 위해서 DB 설계 도중 잘못된 설계를 하여 이러한 부분이 깨지게 될 경우 3가지 정도 부분에서 문제가 일어나게 됩니다. 1. 데이터 삽입 시 문제가 발생하는 삽입 이상 (Insertion Anomaly) 2. 데이터 수정 시 문제가 발생하는 갱신 이상 (Update Anomaly) 3. 데이터 삭제 시 문제가 발생하는 삭제 이상 (Deletion Anomaly) 이제 차례대로 해당 이상현상들에 대해서 살펴보겠습니다. 우선, 이해를 빠르게 하기 위하..
문제 상황 재고가 감소되는 비즈니스 로직에 대해서 트랜잭션 처리를 해주고 비관적 락을 사용해 동시성 처리를 해주도록 해서 동시성을 제어하려고 로직을 짰다. 그리고 테스트를 통해 스레드풀을 생성해서 여러 스레드가 한번에 해당 트랜잭션에 접근하는 환경을 만들어 테스트를 하였다. 분명 Pessimistic Lock을 걸어서 해당 트랜잭션에 순차적으로 접근하도록 했다. 100개의 요청이 순차적으로 처리된다면 값은 0이 되어야 하는데 아래와 같이 순차적으로 처리가 되지 않았다. 어디선가 DB에 락이 제대로 걸리지 않았던가 트랜잭션 처리가 되지 않았거나 둘 중 하나의 문제인 것 같아서 어디가 문제인지 찾아보기로 했다. Pessimistic Lock 설정 위와 같이 쿼리와 함께 락 설정을 해주었다. 아래는 비즈니스 ..
개요 작은 프로젝트를 해보기 위해 내 맥북에 도커를 설치해 컨테이너를 띄우려고 하는 상황에서 발생한 에러이다. 해결한 방법을 공유하고자 한다. brew install docker 홈브루를 통해 도커를 설치했고 mysql 이미지를 pull 해서 사용하려 했는데 다음과 같은 에러가 계속해서 떴다. 우분투 환경에서는 systemctl을 통해서 상태를 확인하고 start를 해주면 그만이지만 mac 환경에는 systemctl이 없다. 그래서 다음과 같은 방법을 통해 문제를 해결했다. 해결 방법 Mac 환경에서 터미널을 통해 docker를 사용하려면 docker desktop on mac 어플리케이션을 설치해주면 된다. 그래서 어디가서 설치하면 되냐? 하면 그럴 필요 없다. brew 명령어를 통하여 다음과 같이 설..
👀 문제상황 mongoDB를 사용하는 도메인의 repository layer의 단위테스트를 하기 위해 테스트 코드를 짜려고 하는 상황이었다. @DataMongoTest 어노테이션을 붙이고 테스트 코드를 짜고 확인하려고 했는데 자꾸 에러가 떠서 테스트에 실패를 했다. 이 문제를 해결하기 위해 로그를 보니 다음과 같은 로그가 찍혀있었다. 나는 @DataJpaTest를 올린적이 없는데 왜 JPA metamodel을 요구하는 거지? 라고 생각했다. 그래서 프로젝트를 만지작 하기도 하고 블로그 글도 찾아보고 열심히 구글링 해보면서 왜 그런지 이유를 알게 되었다. @EnableJpaAuditing 기본적으로 Entity에 생성일자, 수정일자 등의 필드에 값을 넣으려면 LocalDate 클래스로 직접 넣어주는 방식으..
문제 N×M의 행렬로 표현되는 맵이 있다. 맵에서 0은 이동할 수 있는 곳을 나타내고, 1은 이동할 수 없는 벽이 있는 곳을 나타낸다. 당신은 (1, 1)에서 (N, M)의 위치까지 이동하려 하는데, 이때 최단 경로로 이동하려 한다. 최단경로는 맵에서 가장 적은 개수의 칸을 지나는 경로를 말하는데, 이때 시작하는 칸과 끝나는 칸도 포함해서 센다. 만약에 이동하는 도중에 한 개의 벽을 부수고 이동하는 것이 좀 더 경로가 짧아진다면, 벽을 한 개 까지 부수고 이동하여도 된다. 한 칸에서 이동할 수 있는 칸은 상하좌우로 인접한 칸이다. 맵이 주어졌을 때, 최단 경로를 구해 내는 프로그램을 작성하시오. 입력 첫째 줄에 N(1 ≤ N ≤ 1,000), M(1 ≤ M ≤ 1,000)이 주어진다. 다음 N개의 줄에 ..
문제 한수는 크기가 2N × 2N인 2차원 배열을 Z모양으로 탐색하려고 한다. 예를 들어, 2×2배열을 왼쪽 위칸, 오른쪽 위칸, 왼쪽 아래칸, 오른쪽 아래칸 순서대로 방문하면 Z모양이다. N > 1인 경우, 배열을 크기가 2N-1 × 2N-1로 4등분 한 후에 재귀적으로 순서대로 방문한다. 다음 예는 22 × 22 크기의 배열을 방문한 순서이다. N이 주어졌을 때, r행 c열을 몇 번째로 방문하는지 출력하는 프로그램을 작성하시오. 다음은 N=3일 때의 예이다. 입력 첫째 줄에 정수 N, r, c가 주어진다. 출력 r행 c열을 몇 번째로 방문했는지 출력한다. 제한 1 ≤ N ≤ 15 0 ≤ r, c < 2N 풀이 더보기 package baekjoon; import java.io.*; import java..
이중 우선순위 큐 구현 문제였다. min-heap 과 max-heap 두개로 구현해볼까 했는데 뭔가 내가 전혀 모르는 방법이 있을 것 같아서 찾아보니 min-max-heap을 구현하는 방법과 c++의 STL 라이브러리에서 Multiset을 이용한 방법 그리고 내가 사용한 TreeMap을 이용한 구현 방법이 있었다. 먼저 나는 다른 알고리즘 문제를 풀면서 Map 자료구조 중에서는 항상 HashMap 만을 사용해왔었다. TreeMap은 내부가 레드 블랙 트리를 사용하고 있고 삽입, 삭제, 추가 모두 O(log n)의 시간복잡도가 나와서 HashMap 보다는 성능이 떨어진다. 하지만 범위의 검색을 하거나 최댓값, 최솟값을 찾을 때는 TreeMap을 사용하는 것이 효율적이다. 처음에는 구현할 때 중복으로 들어오..
import java.io.*; import java.util.*; public class SubTotal { static BufferedReader br; static StringTokenizer st; static int[] nums; static int n, s, ans; public static void main(String[] args) throws IOException{ input(); solve(); System.out.println(ans); } static void input() throws IOException { br = new BufferedReader(new InputStreamReader(System.in)); st = new StringTokenizer(br.readLine()..
import java.io.*; import java.util.*; class EmptyPoint { int x; int y; EmptyPoint(int x, int y) { this.x = x; this.y = y; } } public class Sudoku { private static final int N = 9; private static final int[] dx = {-1, 1, 0, 0}; private static final int[] dy = {0, 0, -1, 1}; static BufferedReader br; static StringTokenizer st; static int[][] board; static ArrayList emptyPoints; static StringBuilde..