yoni

[30][Network] Thread의 이용 본문

java of educational by contents

[30][Network] Thread의 이용

yoni-1117 2018. 12. 9. 17:13

[01] Thread

 
1. 스레드 개론

1) CPU 관점에서의 스레드의 필요성

   - 네트워크 속도보다 중앙처리장치(CPU)의 속도가 빠름으로 여러명의 접속자가
     시간을 미세하게 나누어, 고성능 CPU를 나누어 쓰는 기능을 제공한다.
     예) 하이퍼 스레딩: 물리적 코아 2개를 SW적인 방법으로 4개로 작동하여 CPU를
         쉬는 시간 없이 좀더 많이 최대한 사용하려는 기술
         I3: 2 Core, Hyper Threading (최소 스펙)
         I5: 2 Core, Hyper Threading + Turbo Booster (권장)
         I7: 4 Core, Hyper Threading + Turbo Booster

 
    - 네트워크 기반의 경우 스레드를 이용하면 CPU 시간을 아주 작게 분리하여 여러개의
      프로세서가 있는 것처럼 작동시키는데 접속자는 마치 자신만 서버를 쓰고 있는 것처럼,
      기다리지 않고 결과를 처리할 수 있다. 스레드는 이런 고성능 CPU의 기능을 최대한 활용하는 
      프로그래밍 기법이다.

    - 시간을 미세하게 나누어 처리하나 고속으로 진행되어 동시처리의 효과를 만들어 낼 수 있는 기술

2) 스레드 사용 분야: Android, 네트워크 프로그램, 미들웨어등 각종 서버(Tomcat...), 게임 제작

3) 인터넷 서버 관점, SW 관점
  - 메모리 공유가 안되 낭비가 심한 인터넷 서버 구조, 하드웨어쪽 관련 분야는 일부 계속 사용
   
   - Thread를 기반으로하여 메모리를 공유하는 효율성이 좋은 인터넷 서버 구조(관리비용 절감)
     (JAVA, JSP는 스레드 기반의 프록그래밍이 가능함)
      


 
4) Socket 기반 Thread
   - 최적화된 네트워크 프로그램 개발
 
5) 스레드 관리자의 실행 주기(Lifecycle)

   - start(): 개발자 호출 -> JVM -> Thread Manager -> 실행 스케줄러 -> run() 호출
     . start(): 개발자가 호출 선언, 스레드 스케쥴러에 등록, JVM에게 실행을 위임함. 
     . run(): JVM이 스레드 스케쥴러를 확인후 그 실행 순서에 따라 run()메소드를
              호출함, CallBack Method(JVM 자동 호출, 개발자가 실행을 선언하지 않음)
             에 해당됨, 스레드로 처리할 로직을 개발자가 선언하는 부분.
     . Thread의 종료는 순환문(while, for)의 종료로 끝납니다.
      

6) Thread와 Exception

    - UnknownHostException e: 접속 컴퓨터가 없는 경우
    - IOException e: 접속된후의 입출력 예외
    - InterruptedException e: 오랫동안 정지된 스레드 발생시
 
 
2. Thread 클래스를 상속받아 구현하는 경우
     java.lang.Object <-- 모든 클래스의 부모
     |
     +--java.lang.Thread <-- 부모
         |
         +--Thread1.java <-- 처리 로직 클래스를 선언
 


 
1) 스레드를 사용하지 않은 경우

[실행 화면]


0: 캐리어 공격
1: 캐리어 공격
2: 캐리어 공격
3: 캐리어 공격
4: 캐리어 공격
0: 드라군 공격
1: 드라군 공격
2: 드라군 공격
3: 드라군 공격
4: 드라군 공격
0: 스카우트 공격
1: 스카우트 공격
2: 스카우트 공격
3: 스카우트 공격
4: 스카우트 공격
 
 
▷ Thread1.java
-----------------------------------------------------------------------------------
package network;
 
class One{
  private String name;
  
  public One(String name){
    this.name = name;
  }
  
  public void run(){
    for (int i=0 ;i<5; i++){
      System.out.println(i + ": " + name);
    }
  }
}
 
public class Thread1 {
 
  public static void main(String[] args) {
    One one1 = new One("캐리어 공격");
    one1.run();
 
    One one2 = new One("드라군 공격");
    one2.run();
    
    One one3 = new One("스카우트 공격");
    one3.run();
 
  }
}
  
  


package network;
 
class Two extends Thread{
  private String name;
 
  public Two() {
    
  }
  
  public Two(String name) {
    this.name = name;
  }
 
  @Override
  public void run() {
    for (int i=1; i<= 100; i++) {
      System.out.println(i + ": " + name);
    }
  }
}
 
public class Thread2 {
 
  public static void main(String[] args) {
    Two one1 = new Two("캐리어 공격");
    one1.start(); // 실행을 JVM에게 위임, run() 호출됨
 
    Two one2 = new Two("드라군 공격");
    one2.start();
    
    Two one3 = new Two("스카우트 공격");
    one3.start();
 
  }
 
-----------------------------------------------------------------------------------
 
 
2) 스레드를 사용한 경우
   - 실행 결과가 섞이지 않으면 순환 횟수를 20번 이상 증가 시키세요.

[실행 화면]

0: 캐리어 공격
1: 캐리어 공격
2: 캐리어 공격
0: 스카우트 공격
0: 드라군 공격
1: 스카우트 공격
3: 캐리어 공격
2: 스카우트 공격
1: 드라군 공격
3: 스카우트 공격
4: 캐리어 공격
4: 스카우트 공격
2: 드라군 공격
3: 드라군 공격
4: 드라군 공격

 
▷ Thread2.java
-----------------------------------------------------------------------------------
package network;
 
class Two extends Thread{
  private String name;
 
 
  .....
 
 
}
 
public class Thread2 {
 
  public static void main(String[] args) {
    Two one1 = new Two("캐리어 공격");
    one1.start(); // run() 호출됨
 
    Two one2 = new Two("드라군 공격");
    one2.start();
    
    Two one3 = new Two("스카우트 공격");
    one3.start();
 
  }
 
 
 
-----------------------------------------------------------------------------------
 
 
3. Runnable 인터페이스를 구현하여 스레드를 실행한 경우
   - 상속은 하나의 class만 가능합니다.
     public class Test extends Thread{ ...             // O 
     public class Test extends Fall{ ...                  // O
     public class Test extends Thread, Fall{ ...       // X, ERROR
   
   - 스레드를 구현하며 상속을 받을 수 있습니다.
     인터페이스는 2개이상 구현이 가능합니다.
     public class Test  extends  Fall  implements Runnable, Fall, Winter{...

[실행 화면]

0: 스카우트 공격
0: 캐리어 공격
1: 캐리어 공격
1: 스카우트 공격
2: 캐리어 공격
0: 드라군 공격
1: 드라군 공격
2: 스카우트 공격
2: 드라군 공격
3: 캐리어 공격
3: 드라군 공격
4: 드라군 공격
3: 스카우트 공격
4: 캐리어 공격
4: 스카우트 공격
   
▷ Thread3.java
-----------------------------------------------------------------------------------
package network;
 
class Three implements Runnable{
  private String name;
 
  public Three(String name){
    this.name = name;
  }
  
  @Override
  public void run(){
    for (int i=0 ;i<5; i++){
      System.out.println(i + ": " + name);
    }
  }
}
 
public class Thread3 {
 
  public static void main(String[] args) {
 
  .....
 
 
    
  }
 
 
 
 
 package network;
 
class Three implements Runnable{
  private String name;
 
  public Three(String name){
    this.name = name;
  }
  
  @Override
  public void run(){
    for (int i=0 ;i<5; i++){
      System.out.println(i + ": " + name);
    }
  }
}
 
public class Thread3 {
 
  public static void main(String[] args) {
    Three three1 = new Three("캐리어 공격");
    // three1.start();
    
    Thread thread1 = new Thread(three1);
    thread1.start(); // 시작
 
    Three three2 = new Three("드라군 공격");
    Thread thread2 = new Thread(three2);
    thread2.start(); // 시작
 
    Three three3 = new Three("스카우트 공격");
    Thread thread3 = new Thread(three3);
    thread3.start(); // 시작
    
  }
-----------------------------------------------------------------------------------


4. sleep() 메소드의 사용
   - 특정 스레드가 CPU 사용을 과도하게 점유하는 것을 막아줍니다.
   - 일정 주기로 부하를 최소화하면서 무한루틴을 실행 할 수 있습니다.
   - 1000ms는 1초를 나타냄

[실행 화면]


현재 경과된 시험 시간: 0 분 1 초
현재 경과된 시험 시간: 0 분 2 초
현재 경과된 시험 시간: 0 분 3 초
현재 경과된 시험 시간: 0 분 4 초
현재 경과된 시험 시간: 0 분 5 초
   
▷ Thread4.java
-----------------------------------------------------------------------------------
package network;
 
public class Thread4 {
 
  public static void main(String[] args) {
    int minute = 0;
    int second = 0;
    
    while(true) {
      try {
        // Thread.sleep(1); // 1000 = 1 초
        second++;
        System.out.println("현재 경과된 시험 시간: " + minute + " 분" + second + " 초");
        
        if ( second == 60) {
          minute = minute + 1;
          second = 0;
        }
      } catch (Exception e) {
        e.printStackTrace();
      }
    }
 
  }
 
}
 
 
 
-----------------------------------------------------------------------------------
 
 


Comments