
- 14 : 스레드풀 생성방법 첫번째
- 처음에 풀 생성시 대기 -> 요청이 오면 스레드 제작 -> 손님이 오면 빌려주고 다쓰고 나면 반납받음
- 반납받은 후 60초가 지나도 이 스레드에 대한 요청이 없으면 해당 스레드를 지워버린다.
- ExecutorService : 스레드 풀 담는 형태
- 17 : 스레드풀 생성방법 두번째
- 기본으로 n개의 스레드를 유지(고정) 하는 방법이다.
- 17 : 현재 CPU에서 사용가능한 스레드 수
- n개만 유지하고 나머지는 반납받으면 지워버린다.
Thread Pool의 작업 생성 (Runnable , Callable)



- 생성된 작업은 execute()와 submit으로 실행된다.
- execute()는 반환값이 없고 예외를 일으킨 스레드를 죽인다
- submit()은 작업 처리 결과를 Future를 통해 반환되고 예외를 일으킨다 해도 스레드를 종료하지 않고 수거해서 재사용

- Runnable 구현받아 스레드 풀 작업 생성
- 12 : n개의 스레드를 유지시키는 방법으로 스레드 풀 생성
- 17 : 반환값 없는 작업을 하려면 Runnable구현받는 class 생성필요
- 여기서 한번만 쓸건데 따로 class만드는 건 낭비 이므로 익명객체 활용하여 할일 만들어줌
- 29 : 스레드 실행 ( 작업 요청, 풀에서 스레드를 빌려주고 반납받고 반복 )
- 반환값 여부 ? Runnable은 반환값이 없다
- 예외시 스레드 재사용 ? 재사용 안한다고 가정
- pool.execute(runnable) : 반환값도 없고 스레드 재사용도 안할거니까 execute로 실행

- Callable을 구현 받아 스레드풀 작업 생성
- Callable은 반환값 있는 작업이다.
- 18 : 반환값을 String으로 지정
- 위와 마찬가지고 익명객체 생성
- 23 : 반환값
- 29 : 스레드 실행 ( 풀에서 스레드를 빌려주고 반납받고 반복 )
- 반환값 여부 ? Callable은 반환값이 있으므로 무조건 submit밖에 사용못함

- 스레드 풀 종료 방법
- shutdown() : 스레드가 다 일을 마칠 때까지 기다려주고 스레드 풀 종료
- shutdomeNow() : 마무리 여부에 상관없이 interrupt를 시켜 중지시키고 종료한다
- 잘 안쓰지만 에러나서 계속 도는 애가 있을 때 사용
- awaitTermination() : 지정한 시간만큼 기다려주고 이후에는 강제 종료
- 시간 내 처리(정상종료) : true , 시간 내 미처리(강제종료) : false
Thread pool blocking
- thread pool에서 runnable과 callable 관계 없이 실행을 submit으로 하면 작업 완료 후 작업 처리 결과를 Future 객체를 반환한다.(execute는 반환타입 없음)
- Future객체를 가져오는 get()메서드는 join()과 같은 역할을 수행한다
- join()은 다른 thread의 종료를 기다린 후에 실행 할 때 사용한다.
- 이것을 blocking이라고 한다

- Runnable에서 블로킹 해보기
- 25 : submit으로 실행해 Future객체를 반환
- Runnable은 반환값이 없지만 submit을 통해 blocking 사용 가능하다.
- 26 : future.get()은 반환값을 뽑아낸다기 보다는 join역할로 사용
- 반환값이 들어오기 전까지는 아래 내용 실행 못함(blocking)
- 블로킹을 해주지 않으면 스레드를 실행하여 다 끝내기 전에 28의 작업완료가 출력되어버린다

- Callable에서 블로킹 해보기
- 18 : callable은 반환값이 있으므로 Integer로 설정해준다
- 31 : Callable은 반환값이 있기 때문에 Future에 반환 타입을 정해줘야한다.
JAVA I/O
- system안으로 또는 밖으로 이동하는 data의 흐름을 stream이라고 한다.
- 스트림이 없으면 데이터를 들여오거나 내보낼 수 없다
- InputStream과 OutputStream으로 나뉘고 바이트 기반과 문자 기반으로 분류된다.

- InputStream과 OutputStream은 바이트 기반 최상위 클래스이다
- 하위클래스에 각각 특화된 분야가 있기 때문에 직접 사용하는 경우는 드물다.

- InputStream과 Output Stream을 사용하는 과정
System.in
- System.in필드는 키보드로 부터 데이터를 입력 받을 수 있도록 돕는다.
- read() 메소드를 사용하면 키보드로 입력한 데이터를 알 수 있다.

- 11 : 키보드로 부터 입력을 받는다
- 14 : read()는 문자를 아스키코드로 받는다
- 15 : 때문에 입력한 문자를 받고 싶으면 char로 캐스팅해주어야 한다.
System.out
- System.out 필드는 콘솔로 데이터를 출력하는데 사용 된다.
- 1개 바이트 출력을 위해서는 OutPutStream의 write(int b) 메서드를 사용한다.
- 문자열 출력을 위해서는 바이트를 배열로 얻은 다음 write( byte[ ]b ) 메서드로 출력한다

- 15 : write()는 byte로 내보내는 것을 문자로 나타난다
- flush() : 밖으로 내보낼 때는 다 사용 후 모두 내보내줘야하기 때문에 flush()를 써줘야한다
- flush()를 사용하지 않으면 문자가 다 나오지 않고 출력될 수도 있다.
- close() : 사용한 자원(Stream)을 닫아주는 역할로 반드시 닫아줘야한다.
Scanner
- 콘솔 클래스는 콘솔로 부터 정수, 실수 값을 바로 읽어드리지 못해서 Scanner클래스를 이용하면 쉽게 얻을 수 있다.

File Class
- File 클래스는 I/O에 해당하는 클래스는 아니다
- java에서 file/directory등을 다룰 수있게 해주는 객체 이다.
- File에 data를 읽고 쓰는기능은 Stream을 통해 이루어진다


- 폴더나 파일을 다루기 위해서는 File객체가 필요하다
- 15 : 파일 객체 생성 new File 괄호에는 경로 설정
- dir.exist() : 해당 폴더나 파일 있으면 true 없으면 false 반환
- c:/img -> mkdir() : 새 폴더 생성
- c:/img/temp -> mkdirs : 폴더 경로 생성
- 이 과정을 실행하면 실제로 C드라이브에 폴더와 파일이 생성된다.
File I/O Stream
- File 객체에 Stream을 활용하면 파일을 복사할수있다.
- 이 때 File에 특화된 FileInputStream과 FileOutputStream을 사용한다.


- 파일 불러오는 법
- 15 : 외부에서 파일 불러오기
- 18 : 파일 객체를 생성하여 불러온 외부파일을 넣어준다
- 21 : InputStream을 준비한다. File에 최적화된 FileInputStream.
- 23 : byte 단위로 읽어온다
- 29 : data에 읽어온 파일을 넣는다.
- 파일의 끝이면 -1을 반환한다
- 30 : data를 char로 바꿔준다.

- 파일 내보내는 법
- 11 ,12 : 읽어올 파일 위치와 내보낼 파일 위치 설정
- 15 , 16 : 읽어올 stream과 내보낼 stream 준비
- 21 : stream 읽어오기
- 22 : stream을 통해 내보내기
- 이 경우는 data를 하나하나 내보내기 때문에 시간이 오래걸린다

- 성능향상을 위해서 byte[]를 사용한다 ( 티스푼으로 옮기던걸 컵으로 옮긴다고 생각 )
- 콘솔을 보면 훨씬 빨라진 것을 알 수 있다.
File reader
- Reader와 writer는 char특화이다.
- 일반 txt문서는 이것 사용하는 것이 편리하다
- 사용법은 File Input Stream과 크케 다르지 않다.

- 10 :읽어올 파일 위치 변수를 따로 지정해 주지 않고 바로 넣었다
- 16 : 기존 배열을 비워주는 기능으로 배열을 비워주지 않으면 새로 채워지지 않은 배열의칸은 전의 값이 그대로 남아있다. 그래서 기존 배열을 비워줘서 반복되지 않게 하는 빈 칸은 그대로 남아서 ㅁㅁ가 나타난다. ( 1024칸이 다 채워지지 않았을 경우 )
- ㅁㅁ는 콘솔에만 나타나 것이라 신경쓰지 않아도 되고 거슬린다면 성능향상을 하지 않으면 된다