Thread Pool 은 대여소 같은 역할을 수행 한다. Thread를 보유 하고 있다가 순서에 따라 빌려 주고, 사용 후 돌려 받는다.
// thread pool 생성 방법
// 처음에 스레드가 없다. -> 요청이 있으면 그때 만든다. ->요청이 있을때 반납받은 스레드가 있으면 그걸 빌려준다.
// 반납받은 스레드가 60초 이상 빌리는 사람이 없으면 폐기한다.
ExecutorService pool1 = Executors.newCachedThreadPool();
// 평소에 기본적으로 n 개의 스레드를 유지한다.
// 현재 cpu 에서 사용 가능한 스레드 수
int n = Runtime.getRuntime().availableProcessors();
System.out.println("thread :"+n );
ExecutorService pool2 = Executors.newFixedThreadPool(4);
-Runnable
// 1. thread pool 생성 -n 개로 고정
int n = Runtime.getRuntime().availableProcessors();
ExecutorService pool = Executors.newFixedThreadPool(n);
// 2. 작업 생성(빌릴때 무엇을 할지 명시 해야 함)
// return 이 있음 : Callable / return 이 없음 : Runnable
Runnable runnable = new Runnable() {
@Override
public void run() {
System.out.println("Runnable 처리");
}
};
// 3. 실행 요청
// Callable 을 구현 받았으면 submit() 로 요청 해야 하고
// Runnable 을 구현 받았으면 execute() 로 요청해야 한다
// 그런데 submit() 으로도 요청 할 수 있다. (Runnable은 둘다 가능)
pool.execute(runnable);
// 4. 스레드 풀 종료 - 더이상 스레드 풀이 할 일이 없을 경우 문을 닫는다.
pool.shutdown(); // 작업 중인 스레드가 있으면 종료까지 기다린 후에 닫는다.
//pool.shutdownNow(); 작업중인 스레드가 있어도 강제 종료시키고 닫는다.
// 특정 시간까지 기다린 후에 스레드를 강제 종료 시킨다.
// API 에서도 shutdown 이후 awaitTermination 을 사용하는 것을 권고
boolean end = pool.awaitTermination(1L, TimeUnit.SECONDS);
// shutdown() 후 종료되지 않은 스레드가 있으면 1초 기다린다.
// 정상적으로 종료되면 true, 강제 종료 시킨게 있으면 false
System.out.println("end :"+end);
-Callable
// 2. 작업내용(Callable)
Callable<String> call = new Callable<String>() {
@Override
public String call() throws Exception {
System.out.println("Callble 실행");
return "complete";
}
};
// 3. 작업 요청(submit)
Future<String> result =pool.submit(call);
System.out.println(result.get());
// Future 객체의 get() 을 사용하면 값을 받아 올 수 있다.
// 4. 스레드풀 종료
pool.shutdown();
boolean end =pool.awaitTermination(1L, TimeUnit.SECONDS);
System.out.println("end :"+end);
작업 종료
Blocking
runnable 과 callable 관계없이 작업 완료 후 Future 객체를 반환 한다
Future 객체를 가져 오는 get() 메서드를 통해 join() 과 같은 blocking 역할을 수행 한다.
Future<Integer> future = pool.submit(call);
// blocking 을 활용 하기 위해서는 Future 객체의 get()이라는 메서드를 사용해야 한다.
int result = future.get();
pool.submit(run).get(); // Runnable 이지만 submit()사용
Network : 서로 다른 computer 끼리 서로 연결 되어있는 망을 의미한다.
// 내 컴퓨터 IP 주소 확인
InetAddress addr = InetAddress.getLocalHost();
// 도메인에 연결된 IP 주소 확인
String domain = "www.gdu.co.kr";
addr = InetAddress.getByName(domain);
System.out.println(domain+" 에 연결된 IP 주소 :"+addr.getHostAddress());
// 대형사이트의 경우 하나의 도메인에 여러 IP 가 붙는다.
domain = "www.youtube.com";
InetAddress[] addrs = InetAddress.getAllByName(domain);
System.out.println(domain+" 에 연결된 IP 주소들...");
Transmission Control Protocol
- 연결 지향 프로토콜로, 데이터를 안전하고 정확하게 전달한다
- 단점은 데이터를 보내기 전 반드시 연결을 형성해야 하며, UDP 보다 속도가 느리다
ServerSocket server = null;
try {
// 1. server 소켓 생성 + 들어올수 있는 포트 개방
server = new ServerSocket(5001);
// 2. client 의 요청 대기
while (true) {
System.out.println("요청 대기중 ...");
// 클라이언트가 접속을 요청하면 수락해 주고
// 요청한 클라이언트의 모든 정보를 socket 으로 받는다
Socket socket = server.accept();
// accept() 는 스레드의 블로킹 기능을 수행한다.
// 3. 받아온 소켓으로 부터 사용자 정보 추출
InetSocketAddress addr = (InetSocketAddress) socket.getRemoteSocketAddress();
System.out.println("접속 요청자의 정보 = " + addr.getAddress() + ":" + addr.getPort());
}
} catch (Exception e) {
// 4. 자원 반납 (서버는 뭔가 문제가 발생한 경우에만 꺼져야 한다.)
server.close();
}
//프로젝트의 bin 폴더에서 cmd 입력
// java ex02.Client
public static void main(String[] args) throws IOException {
Socket socket = null;
try {
// 1. Socket 생성 == 서버에 연결 요청
socket = new Socket("localhost",5001);
// 2. 서버에서 거절한다면 Exception 발생 그렇지 않으면 연결 완료
System.out.println("connect success!!");
// 연결이 성공되면 socket 객체에는 서버에 관련된 모든 정보가 담기게 된다.
} catch (Exception e) {
System.out.println(e.toString());
System.out.println("서버 접속 실패");
}finally {
// 3. 할거 다 했으면 자원 반납
socket.close();
}