Java - 6. Thread

갓김치·2020년 9월 21일
0

고급자바

목록 보기
13/47
post-custom-banner

참고

Process 프로세스

  • 운영체제에서 실행중인 하나의 프로그램
  • 멀티 프로세스: 두개 이상의 프로세스가 실행되는 것
  • 멀티 태스킹: 두개 이상의 프로세스를 실행하여일을 처리하는 것

Thread 스레드

개념과 특징

개념

  • 프로그램의 실행흐름
  • 프로세스 내에서 실행되는 세부 작업 단위
  • 경량화(lightweight) 프로세스
  • 하나의 프로세스 내에는 여러 개의 스레드가 존재 할 수 있다.
  • 멀티스레드: 두 개 이상의 스레드

특징 (vs. Process)

프로세스에 비해 스레드는...

  • 문맥교환(Context Switching) 시간이 적게 걸린다
  • 스레드간의 통신시 시간이 적게 걸린다 (빠르다)
  • 생성 및 종료 시간이 적게 걸린다 (빠르다)
  • 동료 스레드와 사용 메모리를 공유할 수 있다.

Single Thread and Multi Thread

Single Thread

  • Thread가 하나뿐인 프로그램

예시 - T01_ThreadTest.java

* 따로 $ 따로 200개씩 찍힘

public class T01_ThreadTest {
  public static void main(String[] args) { // main thread
    // Single Thread Program
    for (int i = 1; i < 200; i++) {
        System.out.print("*");
    }

    System.out.println();

    for (int i = 1; i < 200; i++) {
        System.out.print("$");
    }
  } // main
} // class

Multi Thread

  • Thread가 2개 이상인 프로그램

예시1 - T02_ThreadTest.java

1단계: Thread 클래스 생성

// 방법 1: Thread클래스를 상속한 class의 인스턴스를 생성한 후,
//        이 인스턴스의 start()메서드를 호출한다.
class MyThread1 extends Thread {
	
  @Override
  public void run() { // Thread클래스의 main 역할을 하는 run()
    for (int i = 1; i <= 200; i++) {
      System.out.print("쿵");
      try {
        // Thread.sleep(시간) => 주어진 시간동안 작업을 잠시 멈춘다.
        // 시간은 밀리세컨드 단위를 사용한다.
        // 즉, 1000ms은 1초를 의미한다.
        Thread.sleep(100);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
  } // run()
} // class MyThread01

// 방법2: Runnable 인터페이스를 구현한 클래스의 인스턴스를 생성한 후
//       이 인스턴스를 Thread 객체의 인스턴스를 생성할 때 생성자의 매개변수로 넘겨준다.
//       이 때 생성된 Thread 객체의 인스턴스의 start() 메서드를 호출한다.
class MyThread2 implements Runnable {

  @Override
  public void run() {
    for (int i = 1; i <= 200; i++) {
      System.out.print("짝");
      try {
        // Thread.sleep(시간) => 주어진 시간동안 작업을 잠시 멈춘다.
        // 시간은 밀리세컨드 단위를 사용한다.
        // 즉, 1000ms은 1초를 의미한다.
        Thread.sleep(100);
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
  }
}

2단계: main()에서 실행

public class T02_ThreadTest {
  public static void main(String[] args) {
    // Multithreaded Program

    // 방법 1: Thread클래스를 상속한 class의 인스턴스를 생성한 후,
    //         이 인스턴스의 start()메서드를 호출한다.
    MyThread1 th1 = new MyThread1();
    th1.start(); // run 으로 실행하면 single thread 방식으로 진행됨


    // 방법 2: Runnable 인터페이스를 구현한 클래스의 인스턴스를 생성한 후
    // 		  이 인스턴스를 Thread 객체의 인스턴스를 생성할 때 생성자의 매개변수로 넘겨준다.
    //		  이 때 생성된 Thread 객체의 인스턴스의 start() 메서드를 호출한다.
    MyThread2 r1 = new MyThread2();
    Thread th2 = new Thread(r1); // Runnable 객체를 매개변수로 받는 생성자
    th2.start();


    // 방법 3: 익명클래스를 이용하는 방법
    //         Runnable인터페이스를 구현한 익명클래스를
    //         Thread 인스턴스를 생성할 때 매개변수로 넘겨준다.
    Thread th3 = new Thread(new Runnable() {
      @Override
      public void run() { // Thread클래스의 main 역할을 하는 run()
        for (int i = 1; i <= 200; i++) {
          System.out.print("쿠");
          try {
            // Thread.sleep(시간) => 주어진 시간동안 작업을 잠시 멈춘다.
            // 시간은 밀리세컨드 단위를 사용한다.
            // 즉, 1000ms은 1초를 의미한다.
            Thread.sleep(100);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
        }
      } // run()
    });
    th3.start();

    System.out.println("★ main 메서드 퇴근 !!! ~ 안녕히계세요 여러분~ ★");
  } // main()
} // class

예시2 - T03_ThreadTest.java

<스레드 수행시간 체크하기>

1단계: 1~10억까지의 합계 구하는 메서드

class myRunner implements Runnable {

  // 1~10억까지의 합계 구하는 메서드
  @Override
  public void run() {
    long sum = 0;
    for (long i = 1L; i <= 1000000000; i++) {
      sum += i;
    }
    System.out.println("합계 : " + sum);
  } // run()
} // myRunner class

2단계: 수행시간 체크

public class T03_ThreadTest {
  public static void main(String[] args) {
    Thread th = new Thread(new myRunner());

    // 1970년 1월1일 0시0분(표준시)로부터 경과한 시간을 밀리세컨드(1/1000초)단위로 나타낸다.
    long startTime = System.currentTimeMillis();

    th.start(); // 쓰레드 시작...

    try {
      th.join(); // 현재 실행중인 쓰레드에서 작업중인 쓰레드 (지금은 th쓰레드)가 종료될 때까지 기다린다.
                 // th.start()의 run()이 실행되는 동안 main을 기다리게 하는 용도
                 // 결론: join()을 이용해서 걸린 시간을 구할 수 있다.
    } catch (InterruptedException e) {
      e.printStackTrace();
    }

    long endTime = System.currentTimeMillis();

    System.out.println("경과 시간 : " + (endTime - startTime) + "ms"); // 464ms

    System.out.println("메인끝");

  } // main()
} // class
profile
갈 길이 멀다
post-custom-banner

0개의 댓글