레이블이 modern-java-in-action인 게시물을 표시합니다. 모든 게시물 표시
레이블이 modern-java-in-action인 게시물을 표시합니다. 모든 게시물 표시

2021-12-27

12/27 반복자의 상태와 컬렉션의 상태가 다를때 발생하는 에러

 


반복자의 상태와 컬랙션의 상태가 동기화 되지않기 때문에 에러가 발생한다.

(for-each문은 내부적으로 iterator로 해석됨.)

iterator를 명시적으로사용하고 remove를 호출하면 이러한 문제를 해결할 수 있지...만!!

이때문에 removeIf라는 메서드가 등장하였다!

2021-12-26

12/26 무한스트림 OOM을 주의하기 ㅋㅋㅋ

 

무한스트림을 생성한후 limit하는 걸 까먹었더니 생전처음 oom을 만났다... 웃기다 ㅋㅋ

12/26 비동기 논블로킹 서블릿 스레드

 1. 서블릿 스레드가 요청(작업)을 받는다(서블릿 스레드 풀에서.)  

2. 비지니스 로직을 처리한다 -> 이부분을 워커 스레드에게 위임하고 return

3. 워커스레드가 돌아오면, 서블릿스레드 풀에 그 작업이 다른 스레드에게 할당. 유저에게 response를 준다. 

-

논블로킹이 아니었을 경우

->2번에서 블로킹이 일어나므로. 해당 스레드 대기큐로 들어가서 쿨쿨 잔다.

-> 메모리 사용량은 올라가는데 cpu는 놀고있는 비효율적인 상황발생.

-

비동기 블로킹 / 비동기 논블로킹을 잘 구분해야!!


2021-12-25

12/25 람다 혹은 익명클래스 외부변수 접근 제약





 Variable used in lambda expression should be final or effectively final

- 람다, 익명클래스는 다른 스레드에서 실행될 수 있다.

- 만약에 람다,익명클래스가 외부변수에 자유롭게 접근할수있다고 해보자.

- 그 람다/익명클래스를 만든 스택은 이미 사라지고 free변수도 사라졌는데, 람다/익명클래스는 그 지역변수를 계속해서 참조하려고 하는 에러가 발생한다.

- 따라서 , final 혹은 effectively final 인 외부변수에만 람다/익명객체는 접근할 수 있다.

-원래는 final키워드를 명시적으로 붙이는것이 맞으나 1.7부터는 컴파일러가 알아서 붙여준다고 한다.

-그러므로 - 결론적으로 :

- 람다/익명객체는 외부변수에 자유롭게 접근 가능하다.

- 그러나 지역변수의 경우 스택에 위치하므로, effectively final한 특성을 가지고 있어야 한다.

- 위 코드의 경우 effectively final 해야한다는 특성을 어겼으므로 컴파일러가 final키워드를 붙여서 처리해줄수없다. 따라서 에러가 난다.


2021-12-24

12/24 스레드 무한정 생성해보기

 유투브가 버벅대고 다른 프로그램이 열리지않게 됨 ㅋㅋㅋㅋ 재밌다 ㅋㅋㅋ

스레드 무한생성하는 main두개 돌린결과..





12/24 리액티브 모델

 1. 메시지 드리븐 / 이벤트 드리븐

message driven : 하나의 목적지를 향한다.

event driven : 해당 이벤트가 등록된 컴포넌트를 향한다.

-> 이벤트 드리븐 모델에서는 특정 메시지와 특정 어플리케이션이 결합되지 않도록 하여, 유연성을 유지하고자 한다. 

2. 리액티브 프로그래밍 

- 반응성 : 유저에게 밀리세컨드 단위로, 좀더 빠르게 응답할수있어야 한다. 

- 회복성 : 장애가 일어났을때 회복할수있는 방법이 있어야 한다. 작업을 다른 어플리케이션에게 위임한다던지 등등. 

- 탄력성 : 부하가 가해졌을때 크기를 확장하는 등 탄력적으로 대응할 수 있어야 한다. 

- 이벤트 드리븐 : 발행 - 구독 방식으로 대응할 수 있어야 한다. 

3. 이벤트 드리븐 방식으로 인하여, 어떠한 하나의 어플리케이션에 장애가 일어나더라도 그 장애는 다른 어플리케이션으로 전파되지 않는다. 직접적으로 메시지로 연결되어있지 않기 때문이다. (kafka나. messageMQ를 쓰는데는 다 이유가 있던것이다...) 어떤 어플리케이션에 장애가 일어날 경우, 그 어플리케이션은 회복될때까지 격리된다. 
- 만약에 메시지 드리븐 방식이었다면, 해당 메시지가 특정 어플리케이션을 직접적으로 가리키므로, 장애가 일어나면 장애가 계속 연쇄적으로 전파되었을 것이다. 

- 하나의 공통된 DB에 의존하기 보다 카프카와 같은 발행-구독 기반 모델을 사용하여, 서로간의 결합도를 낮추고 - 좀더 장애에 탄력적인 서비스를 제공할 수 있게 된다.

12/24 블로킹과 논블로킹

 



일반적인 메서드의 경우 delay가 되는동안 - 해당 스레드는 아무작업을 하지않고 룰루랄랄라 하면서 네트워크/IO/DB에서 데이터 읽어오기 등등... 의 결과가 돌아오는 것을 기다린다. 이 동안 블로킹이되며 해당 스레드가 맡고있는 태스크가 있기 때문에 다른 작업이 할당되지 않는다. 


그러나 논블로킹으로 할경우 , 작업을 다른 스레드에게 맡기고 - 호출된 스레드는 바로 반환된다. 이렇게 함으로써 반환된 스레드는 다른 작업을 하고 있을 수 있다. CPU 연산작업도 하면서 네트워킹 기능도 수행하고 이렇게 효율적으로 스레드 자원을 사용할 수 있는것이다.

이러한 작업을 CompletableFuture 혹은 Future 를 통하여 구현할수있다. 

단 Future.get() 메서드를 불렀을때 작업이 완료되지않은 상태이면 그동안 블로킹이 되는데, 그렇기 때문에 타임아웃을 설정하는 등 고려해볼 수 있다. 

12/24 블로킹 주의하기

1. 블로킹이 되는 경우 : 스레드가 잠을 자는 상황 - 

 - 어떤 동작을 완료하기를 기다리거나 (Future 의 get 메서드)

- 외부와의 상호작용을 기다리는것 - (네트워크 통신, 데이터베이스 서버에서 데이터 가져오는 것 기다리기, 키보드 입력 기다리기 ) 

2. 블로킹이 되면, 해당 태스크가 할당된 스레드는 쿨쿨 잠잔다. 중요한 자원의 낭비!!

3. 따라서 블로킹이 될경우. 해당 스레드가 다른 작업을 할 수 있게끔 해야한다!!

4. ScheduledExecutorService를 통하여 이것을 할수있다

- 작업을 할당하고 - 자는동안. 블로킹을 해서 마냥 기다리는 것이아니라. 블로킹이 되면 일단 해당 스레드 종료!

 그리고 나서 네트워크통신이든 데이터베이스든 다시 입력이 들어오면. 스레드에게 작업을 할당하여 완료할수있도록 스케쥴링!!

12/24 스레드풀의 사용 주의점, concurrent 프로그래밍의 주의점

 1. java 5 부터 Executor와 ExecutorService를 제공한다. 

- 장점: 이를통하여, 이제 개발자는 스레드를 직접 다루지 않고 동시성프로그래밍을 하는 것이 가능해졌다.

- 어떠한 작업을 실행할지를 정의하는 것과, 작업을 제출하여 실행하는 것을 분리하였다. 

- ExecutorService가 스레드 스케쥴링 .. 큐 우선순위.. 작업할당을 알아서 해주므로 매우 편리하다!!

- 단점 : ExecutorService는 , 하나의 스레드에 하나의 작업만을 할당한다. 따라서, 만약에 5개의 스레드중 앞의 3개의 스레드가 잠을자거나 / IO요청이 일어나거나 /네트워크통신을 해야한다면 - 이들은 idle하게 놀고있음에도 불구하고, 이미 할당된 task가 완료되지 않아 룰루랄라하는 비효율적인 상황이 발생한다. 결국 남은 2개의 스레드가 나머지 작업들을 뻘뻘 해야한다. ㅠㅠ

2. concurrent 와 parallel의 차이

- fork-join을 생각하면, parallel로 이루어지는 작업에 대하여 보다 직관적으로 이해할 수 있다. 어떠한 작업을 제출하고, 그 반환을 메서드 안에서 기다린다. (엄격한 fork-join) 이것은 여러 스레드가 동시에 실행할 수 있다. 메서드가 시작되고 완료된 값을 return 한다. 분할 정복. 

- 반면, concurrent - 이를 테면, 여러 클라이언트의 작업을 동시에 처리하는 웹 서버. 는 상황이 다르다... 

- 비동기 프로그래밍이란, 메서드의 실행 -> 반환이 완료된 후에도, 그 작업이계속해서 이루어지는 것이다. 

3. 비동기 프로그래밍의 주의점

- 메서드가 실행되고, 반환 (return ) 된 이후에도 만들어진 태스크 실행이 계속되는 메서드를 비동기 메서드라고 한다. 

- 어떠한 문제가 발생할수있는가 ? 우선 '종료된 이후에도'라는 측면에 초점을 맞추어 생각해보자. 

- jvm은 유저가 만든 중요한 작업이 main이 실행된 후에도 계속될수있게끔 하기위하여 - main이 종료되더라도, 실행중인 task 가 있다면 종료되지 않는다. 하지만 그러면 메모리 leak이 발생하거나. 프로그램이 crash될 것이다. 

- 그럼 main이 종료될때 남아있는 task를 전부 강제종료 해버리자 ? -> 만약에 해당 task가 IO를 수행하면서 디스크에 파일을 쓰고있었는데 갑자기 강제종료당해서 작업이 중지된다면? 해당 파일은 못쓰는 파일이 될것이고 데이터에 손상이 가해질 것이다. 

-> 이러한 문제점의 해결책으로, setDemon을 하여 주요작업스레드가 종료되면 함께 종료하게 하거나.. ExecutorService와 같은 프레임워크를 사용하고 있는 경우 우아하게 종료를 해주는 습관을 가지는 것이 중요하다!!! 

- 어떤 스레드에 어떤 작업을 할당하였는지 추적하는 사고를 가지자!!

12/24 자바 동시성 프로그래밍

 1. 자바 동시성 프로그래밍 

2. 서비스 제공 환경의 변화

- 이제는 독립적으로 모든 서비스를 제공하는 어플리케이션 보다는.

- 여러 서비스들을 매쉬업하여 제공하는 서비스가 대부분이고

- 이 때문에. 마이크로서비스라는 모델도 등장하게 된것이다 - 

3. 서비스 매시업

- 이를테면 구글의 검색결과를 바탕으로 필터링한 데이터를 번역하고 트위터에서도 검색한 결과를 필터링하고... 그런 서비스를 제공해주고 싶다고 하자

- 그러면. 구글에서 검색한결과를 찾아오는 동안 해당 스레드가 블로킹되면 많은 지연이 발생할것이다

- 구글검색결과를 가져올동안. 트위터에서도 검색결과를 받고 번역작업을 동시에 실행하고 싶은것 - 

- 이를 달성하기 위하여 동시성 프로그래밍을 하고 성능향상 효과를 기대해 볼 수 있다

4. 동시성 / 병렬성

- 동시성은. 연관된 작업을 단일 코어 머신에서도 실행할 수 있다

- 병렬성은 하드웨어 수준에서 멀티코어를 지원할때 실행 . 여러작업을 fork -> join 하기 때문에. 외부 데이터에 영향을 받지 않는 안전한 함수여야 한다. 결합법칙이 성립해야한다. 

0328 fdisk, mkfs, mount, fstab

 1. 하드디스크를 붙인다. 2. fdisk -l로 하드디스크를 확인한다.  - interactiive한 커맨드모드 사용하여 (m) 붙인 하드디스크의 파티셔닝을 한다.  - 마지막에 w를 해야 실제로 반영이 된다.  3. mkfs를 하여 어떤 파일시스...