본문 바로가기

Java 공부

12장 스레드풀(2)


블로킹 방식이란?

무언가를 요청을 하고 나서 요청의 결과가 나올때까지 기다리는 방식을 이야기 한다.


블로킹 방식의 작업 완료 통보 받기

리턴타입 

메소드명(매개변수) 

설명 

 Future<?>

 submit(Runnable task)

 - Runnable 또는 Callable을 작업 큐에 저장

 - 리턴된 Future를 통해 작업 처리 결과를 얻는다.

 Future<?>

 submit(Runnable task, V result)

 Future<?>

 submit(Callable<V> task) 


Future

-작업 결과가 아니라 지연완료(pending completion)객체

-작업이 완료될 때까지 기다렸다가 최종 결과를 얻기 위해서 get()메소드를 사용한다.

리턴타입 

메소드명(매개변수) 

설명 

get() 

작업이 완료될 때까지 블로킹 되어있다가 처리결과 V를 리턴 

V

get(long timeout, TimeUnit unit) 

 timeout 시간동안 작업이 완료되면, 결과 V를 리턴하지만, 

작업이 완료되지 않으면 TimeoutException을 발생시킴


메소드 

 작업 처리 완료후 리턴 타입

 작업 처리 도중 예외 발생

 submit(Runnable task)

future.get() -> null 

 future.get() -> 예외 발생

 submit(Runnable task, Integer result)

future.get() -> int 타입 값

 future.get() -> 예외 발생

 submit(Callable<String> task)

future.get() -> String 타입 값 

 future.get() -> 예외 발생


*submit(Runnable task) 

  Runnable 객체는 결과 값이 없는 작업객체를 말한다. 따라서 결과가 없기 때문에 future.get()은 null을 리턴

*submit(Runnable task, Integer result) 

  Integer result는 스레드가 작업을 처리한 후의 결과값을 말한다. 따라서 future.get()은 int 타입 값을 리턴

*submit(Callable<String> task)

  Callable의 작업 처리 결과가 String으로 나온다는 뜻이고, future.get()은 String타입 값을 리턴한다.


get()은 "스레드가 작업을 완료할 때까지 멈춰서 기다린다"는 뜻이다. 


따라서


Future의 get()은 UI 스레드에서 호출하면 안된다.

-UI를 변경하고 이벤트를 처리하는 스레드가 get()메소드를 호출하면 

-작업을 완료하기 전까지는 UI를 변경할 수 도 없고, 이벤트를 처리할 수도 없게 된다.

-따라서 다음과 같이 두가지 방법으로 get()메소드를 호출 할 수 있다.

1) 새로운 스레드를 생성해서 호출 

2) 스레드 풀의 스레드가 호출 

new Thread(new Runnable() {

    @Override

    public void run() {

       try {

            future.get();

          } catch(Exception e) {

             e.printStackTrace();

          }

      }

}).start();


 executorService.submit(new Runnable() {

     @Override

      public void run() {

            try{

              future.get();

            } catch(Exception e) {

                e.printStackTrace();

           }

      }

 });


1) 새로운 스레드를 익명객체로 즉시 생성하여 바로 start()메소드로 실행하기

2) future.get()을 처리하는 작업 객체인 Runnable객체를 만들어서 스레드 풀의 스레드가 작업을 처리하도록 요청한다.


다른 메소드

리턴타입 

메소드명(매개변수) 

설명 

 boolean

cancel(boolean mayInterruptIfRunning) 

작업 처리가 진행중일 경우 취소시킴 

 boolean

 isCancelled()

작업이 취소되었는지 여부 

 boolean

 isDone()

작업 처리가 완료되었는지 여부 


리턴값이 없는 작업 완료 통보


Runnable task = new Runnable() {

@Override

public void run() {

//스레드가 처리할 작업 내용

}

};

Future future = executorService.submit(task);


try {

future.get();

} catch(InterruptedException e) {

//작업 처리 도중 스레드가 interrupt 될 경우 실행할 코드

} catch(ExecutionException e) {

//작업 처리 도중 예외가 발생된 경우 실행할 코드

}


1) 리턴값이 없는 작업 객체(Runnable)를 만든다.

2) 작업 객체 task를 매개변수로 하여 submit메소드로 작업객체를 작업 큐에  넣어준다.

   이때, submit메소드는 Future라는 객체를 리턴한다.

3) future를 가지고 스레드가 작업을 완료했는지, 처리도중인지 알 수 있다.

4) future.get(); 스레드가 작업을 완료할 때 까지 기다린다 는 뜻으로  get을 호출하게 되면 블로킹이 발생하게 되고, 

   스레드 풀의 스레드가 작업을 완료할 때 까지 future.get()메소드를 실행한 스레드는 멈춰있게 된다.

   여기서는 작업 결과가 없기 때문에 future.get()은 null을 리턴한다 따라서 값을 담을 변수도 필요하지 않다.

5) get()메소드에서 발생할 수 있는 예외는 두가지이다.

   InterruptedException, ExecutuionException 



본 포스팅은 이것이 자바다 책을 참고하여 작성하였습니다.



'Java 공부' 카테고리의 다른 글

12장 스레드풀(4)  (0) 2018.12.12
12장 스레드풀(3)  (0) 2018.12.11
12장 스레드풀(1)  (0) 2018.12.09
12장 스레드 그룹  (0) 2018.12.09
12장 데몬 스레드  (0) 2018.12.08