[ Java.Thread-4. Thread Pool-2 (예제) ]


1. JDK안의 쓰레드 풀들

   - JDK 1.5버전 이전까지는 유저들이 직접 쓰레드 풀을 만들어 사용했다. 유저가 직접만드는 방식은 귀찮기도 했고, 쓰레드간의 Context Switching시에 성능문제도 발생했다.  JDK1.5에서는 java.util.concurrent패키지가 포함되었는데 여기에는 다양한 방식의 쓰레드 풀이 기본으로 포함되게 되었다.


2. Executors.newFixedThreadPool(10)

   - 정의 : 최대 쓰레드를 10개까지 만드는 풀.  

             동시에 일어나는 업무의 량이 비교적 일정할때 사용한다.

   - 소스 : newFixedThreadPool(2) 를 이용해서 2개의 Pool을 생성한 후 execute()를 사용해 

            연속적으로 5개의 ThreadTask Instance생성을 시도 한다. 

            각 ThreadTask는 1초씩(Thread.sleep(1000)) 수행시간이 걸린다.

            Pool이 2개 이므로 5개를 요청했지만 instance는 2개씩만 생성 된 후 instance가 종료되면

            다음 instance가 생성 된다.


   - NewFixedThreadPoolMain.java

      

   - ThreadTask.java
      

   - 수행결과
      




Posted by 농부지기
,

[ Java.Thread-3. Thread Pool-3 (기본개념) ]


1. 정의

   - 자바의 쓰레드는 CPU를 최대한 사용해서 많은 업무를 동시에 처리할수 있도록 도와준다. 그런데 이 쓰레드의 생성에는 약간의 시간과 메모리가 필요하다. JVM은 쓰레드의 생성 개수를 제약하지 않기 때문에 계속적으로 쓰레드를 생성하게 된다면 결과적으로 성능저하와 메모리 고갈의 문제가 생길수 있다. 

 

   - 이렇게 무제한 적인 쓰레드의 생성을 막기 위해서,  쓰레드풀(Thread Pool)이라는 쓰레드 관리 방식이  사용되고 있다. 쓰레드 풀이란 쓰레드를, 허용된 갯수 안에서만 사용할수 있도록 스스로 제약하는 방식이다.  이것은 JVM의 옵션등으로 제어할 수는 없고, 어플리케이션이 선택적으로 사용하는 방법이다.


   - 쓰레드풀 방식을 사용하는 대표적인 소프트웨어는 Tomcat같은 웹서버들이다. 웹서버들은 동시에 많기는 수천~수만의 요청이 들어올수 있는데, 이때마다 쓰레드를 생성하는 것은 JVM의 메모리를 급속하게 소비시키며 성능에도 저하가 발생하게 된다. 이럴때 최대 쓰레드 갯수를 지정해 놓으면 쓰레드 갯수 이상의 HTTP 요청에 대해서는 처리하지 않고  기다렸다가 놀고 있는 쓰레드가 생기면 그때 HTTP 요청을 쓰레드를 통해 처리한다. 



2. 쓰레드 풀의 구조

   쓰레드 풀은 크게 3가지 부분으로 나눈다. 


   1) Task의 요청을 받는 Queue부분

   2) 실제 쓰레드를 생성하고 관리하는 하는 manager 부분

   3) Queue 안에서 Task를 꺼내와서 실제 쓰레드 위에서 동작시켜 결과를 얻는 부분


   [ 풀 구조 - 이미지]



Posted by 농부지기
,

[ Java.Thread-3. Thread예제-3 (쓰레드 이름) ]



1. 소스 목록 : ThreadMain.java


2. ThreadMain.java

   - 쓰레드 이름을 얻고

     쓰레드 이름을 설정하고

     쓰레드 이름을 출력한다.


4. 수행결과

   - 매번 수행 시 결과는 계속 달라진다.


5. ThreadMain .java


6. 수행결과 (매번 수행시 결과 순서는 다르다.)
 



Posted by 농부지기
,

[ Java.Thread-3. Thread예제-2 ]


1. 소스 목록 : ThreadMain.java

                DigetThread.java

                AlphaThread.java


2. ThreadMain.java

   - 쓰레드를 상속받지 않았지만 메인 쓰레드가 된다.

   - DigetThread, AlphaThread의 instance를 생성 후 start()하게 되면   run()메소드가 수행된다.

     Thread를 상속받은 instance diget, alpha는 메인쓰레드와 관계 없이 각 각 별도로 수행된다.


   - 쓰레드 instance를 수행(start, run) 후 diget.sleep(1000);를 하게 되면 

     소스상으로 보면 diget이 1초 멈춤효과를 내야하지만  diget이 계속 수행되는걸 알 수 있다.

     >> 그 이유는 sleep()이 항상 현재 실행중인 쓰레드에 대해 작독하기 때문에 diget.sleep(1000)과 같이 호출하였어도 실제 영향을 받는 것은 main메서드를 실행하는 메인쓰레드가 된다.

         그래서 sleep()은 static으로 선언되어 있으며 참조변수를 이용해서 호출하기 보다는 Thread.sleep(1000);을 해야 한다.


4. 수행결과

   - main()에 의해서 메인쓰레드가 수행

   - DigetThread, AlphaThread생성 후 start()에 의해서 run()메소드 수행

     이때 DigetThread, AlphaThread의 실행순서, for문  실행순서는 매번 달라진다.

     이 부분은 JVM에 따라 언제든 달라진다.

     이때문에 반드시 Thread 프로그램들은 서로 관여하지 않는 프로그램을 작성해야 된다.

   - diget.sleep(1000); 에 의해서 메인쓰레드는 1초간 정지 (Thread.sleep(1000); 과 동일함)

   - alpha.sleep(1000); 에 의해서 메인쓰레드는 1초간 정지 (Thread.sleep(1000); 과 동일함)

 

5. ThreadMain.java


6. DigetThread.java

7. AlphaThread.java


8. 수행결과


Posted by 농부지기
,

[ Java.Thread-3. Thread예제-1 ]


1. 소스 목록 : ThreadMain.java

                ThreadExe1.java

                ThreadExe2.java


2. ThreadMain.java

   - 쓰레드를 상속받지 않았지만 메인 쓰레드가 된다.

   - ThreadExe1, ThreadExe2의 instance를 생성 후 start()하게 되면   run()메소드가 수행된다.

     Thread를 상속받은 instance th1, th2는 메인레드와 관계 없이 각 각 별도로 수행된다.


   - 레드 instance를 수행(start, run) 후 th1.sleep(3000);를 하게 되면 

     소스상으로 보면 th1이 3초 멈춤효과를 내야하지만  th1이 계속 수행되는걸 알 수 있다.

     >> 그 이유는 sleep()이 항상 현재 실행중인 레드에 대해 작독하기 때문에 th1.sleep(3000)과 같이 호출하였어도 실제 영향을 받는 것은 main메서드를 실행하는 메인레드가 된다.

         그래서 sleep()은 static으로 선언되어 있으며 참조변수를 이용해서 호출하기 보다는 Thread.sleep(3000);을 해야 한다.


4. 수행결과

   - main()에 의해서 메인레드가 수행

   - ThreadExe1, ThreadExe2 instance생성 후 start()에 의해서 run()메소드 수행

     이때 ThreadExe1, ThreadExe2의 실행순서, for문  실행순서는 매번 달라진다.

     이 부분은 JVM에 따라 언제든 달라진다.

     이때문에 반드시 Thread 프로그램들은 서로 관여하지 않는 프로그램을 작성해야 된다.

   - th1.sleep(3000); 에 의해서 메인쓰레드는 3초간 정지 (Thread.sleep(3000); 과 동일함)

   - th1.sleep(3000);가 있기 때문에 쓰레드 instance2개가 먼저 종료되고, 메인쓰레드가 종료 된다.

   - 만약,  th1.sleep(3000); 가 없다면 메인쓰레드가 먼저 종료 된다.


5. ThreadMain.java


6. ThreadExe1.java

7. ThreadExe1.java

8. 수행결과


Posted by 농부지기
,

[ Java.Thread-2. Thread만드는 방법 ]


1. java에서 Thread만드는 방법

   - 자바에서는 쓰레드를 만드는 방법이 두 가지 존재 한다.

   - API차원에서 쓰레드를 지원해주고 내가 만드는 클래스를 쓰레드로 만들어 작업을 하려면 클래스를 쓰레드클래스로 만들어야 한다.

   1) Thread 클래스를 상속받아 작성

   2) Runnable 인터페이스를 상속받아 작성



2. Thread 클래스를 상속받아 작성 방법

    1) Thread클래스를 상속받는 클래스를 작성한다.     

        public classs 클래스명 extends Thread {}


    2) public void run()를 오버라이딩한다.

       => 독립적인 실행흐름으로 작성하고 싶은 코드를 run메서드에 구현한다.

 

                 public void run(){

                     //여기에 구현

                  }


     3) 쓰레드 객체를 생성하여 start()를 호출한다.

       => start()에 의해서 JVM이 쓰레드 프로그래밍 작업을 수행할 준비를 하며 내부 스케쥴러에 의해서 적절한 시기에 run 메서드가 호출된다.



3. Runnable 인터페이스를 상속받아 작성 방법

    => 다른 클래스를 이미 상속받고 있는 경우 'Thread클래스를 상속받아 작성하는 방법'만 지원하면 멀티쓰레딩을 할 수 없다.

       따라서, Runnable을 구현하는 방법을 통해 다른 클래스를 이미 상속받고 있다고 하더라도 멀티 쓰레드를 구현 할 수 있다.

   1) Runnable 인터페이스를 상속한다.

      public class 클래스명 extends 상위클래스 implements Runnable{ 

         ....

      }

   2) run 메서드를 오버라이딩한다.

       => Thread 클래스를 상속받을 때와 동일한 방법으로 run을 오버라이딩하여 독립적인 흐름으로 실행하고 싶은 내용을 기술한다.

           public void run(){

            ...

           }


   3) thread 객체를 생성한다. 

      이 때 작성해놓은 Runnable을 상속받는 객체를 생성해서 매개변수에 지정한다.

       Runnable 하위객체 obj = new Runnable 하위객체();

       Tread t = new Tread(obj);


   4) thread 클래스의 Start를 호출한다.

      => Start를 호출하면 내부적으로 Thread 객체를 생성하면서 전달받은 Runnable 하위객체의 run을 호출한다.

         (역시 적절한 시점에 JVM에 의해 호출)



Posted by 농부지기
,

[ Java.Thread-1. 기본개념 ]



1. Thread 정의

   - 프로그램이 실행되는 순서는 코드를 위에서 아래로 순차적으로 처리 되는 방식을 가진다.

     예) "선언문 -> 분기문 -> 반복문 -> 리턴"구조로 개발했을 경우 

         프로그램의 실행순서도 "선언문 -> 분기문 -> 반복문 -> 리턴"순서 그대로 처리 된다.


    - 이러한 흐름을 (Thread)에 비유해서 스레드(Thread)라고 한다.

      일부러 스레드를 개발하려 하지 않아도 기본적으로 메인스레드(Main Thread)구조로 작동된다.

      메인스레드는 시스템이 우리의 프로그램을 돌리기 위한 가장 기본적인 스레드가 된다.

   

    - 그래서 우리는 이 시스템 스레드인 메인 스레드를 제어하거나 컨트롤을 할 수 없다.

      하지만 자바에서는 프로그래머가 직접 제어하거나 컨트롤 할 수 있는 스레드를 생성하여 사용할 수 있다.

      이러한 스레드를 워킹스레드(Working Thread)라고 한다.


2. Thread 사용이유 1

   - 예를 들어, 서버 기반의 스마트폰 게임을 보면

     서버와 통신을하기 위해 소켓을 열어두고 대기하게 된다.

     하지만 소켓만 열어두고 가만히 있으면 이 소켓이 끊겼는지 아니면 끊기지 않았는지 알 방법이 없다.

   - 그래서 소켓 통신에서는 일정 주기마다 서버로 핑을 날려 이 소켓이 유효한지 아닌지 검사하게 된다.

   - 또, 소켓 통신에서는 일정 주기마다 서버로부터 온 데이터를 확인하고, 서버로 보낼 메시지를 전달한다.

   - 이러한 일련의 작업을 메인스레드에서 하게 된다면 어떻게 될까?

     메인스레드는 게임을 하기 위한 UI(User Interface)부분을 그려주고 그래픽 부분을 담당하게 되는데 코드는 순차적으로 실행되기 때문에 UI를 그리는 동안 정작 통신을 담당하는 소켓부분을 방치하는 수 밖에 없다.

     그러므로 통신을 담당하는 스레드를 하나두어 일정한 시간단위로 체크할 수 없도록 하게 하는 것이다.

    

3. Thread 사용이유 2

   - 영상통화를 하는 예,

   - 간단하게 영상을 받아 뿌려주는  소스와 영상을 만들어 보주는 소스.

     이 두 가지 작업이 동시에 수행 되어야 됨.

     이렇게 두 가지 이상의 일을 스레드를 통해 구현된 프로그램을 멀티스레드 프로그램(Multi Thread Progradm)이라고 한다.


4. Thread  종류

   - 메인스레드 : 프로그램을 실행하기 위한 시스템 스레드

   - 워킹스레드 : 프로그램머가 생성하고 제어할 수 있는 스레드 


5. 워킹스레드

    - 워킹스레드는 메인스레드에서 생성하여 실행하게 된다.

      그렇다고 워킹스레드가 메인 스레드에 종속되었다고 보기 힘들다.

      왜냐하면 한 번 실행된 워킹스레드는 메인스레드가 종료되어도 단독으로 실행되기 때문이다.

    - 그래서 메인스레드는 종료될 때 사용중인 모든 워킹스레드를 종료하고, 마지막에 자신이 종료되어야 한다. 

    - 그렇게 하지 않는다면 메모리와 CPU의 자원을 워킹스레드가 다 차지하게 되어 시스템이 뻗어버릴것이 자명하기 때문이다.

       (메인스레드를 종료할 때 반드시 워킹스레드를 종료해야 한다.)

 

Posted by 농부지기
,

[ Socket(TCP/IP).서버와 클라이언트 코딩 과정 ]


1. 서버와 클라이언트간에 메세지전송시 코딩 과정을 그림으로 도식화 해 봤다.

   도식화 이미지 : http://www.crocus.co.kr/425   (C언어도 작성됨.  소켓 개념파악에는 좋음)


2. 서버단

   1. Socket

      - 소켓은 커널의 입장에서는 커뮤니케이션의 종점이다. 

      - 프로그램 입장에서는 읽고/쓰기를 네트워크를 통해 가능하게 해주는 역할이라고 볼 수 있다.

        즉, 소켓은 데이터가 들어오고 나가는 출입구 같은 역할을 한다.

   2. Accept

      - accept() 함수로 클라이언트측 주소정보를 저장할 공간을 만들고 대기상태로 만든다.


3. 클라이언트 단

   1. Socket

      - 서버와 마찬가지로 통신을 위한 소켓을 정의 하고 열어야 한다.

   2. Connect

      - 서버의 주소를 담고있는 addr 구조체를 이용하여 서버에 접속을 시도한다.

Posted by 농부지기
,