ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Thread
    과거/Java 2021. 3. 17. 16:30

    1. 개요

     1) 하나의 프로세스에서 실행하는 작업 = 하나의 프로세스가 실행되면 하나의 스레드가 실행됨

     2) 메인 스레드 작동 = 프로세스 시작

     3) 프로세스 내부에 하나의 스레드가 동작 = 싱글 스레드 프로세스

     4) 프로세스 내부에 여러 개의 스레드가 동작 = 멀티 스레드 프로세스

     

    2. 프로세스

     1) 운영체제로부터 실행에 필요한 자원인 메모리를 할당받아 실행 중인 프로그램

     2) 수행에 필요한 데이터, 메모리 등의 자원 그리고 스레드로 구성

     

     ※ 멀티 프로세스

      (1) 여러 개의 CPU 프로세스가 작업을 병행 처리하는 기법

      (2) CPU 프로세스들은 독립적으로 여러 대의 컴퓨터에서 분산 처리할 수 있는 장점이 있음

      (3) 각 프로세스는 자원을 독립적으로 할당받아야하므로 자원 소모가 많고 통신과 작업을 나누고 합치는 과정이 복잡

     

    3. 멀티 스레드

     1) 하나의 프로그램에 여러 개의 스레드가 실행 = CPU 사용률 향상

     2) 자원 공유로 가볍고 각각의 스레드를 제어할 수 있어 성능 향상에 용이 = 자원의 효율적 사용

     3) 여러 개의 스레드가 동시에 처리하는 것처럼 보이나, 실제로는 스케줄러에 의해 병행처리됨 = 사용자에 대한 응답성 향상

     

     ※ 스레드 스케줄러

      (1) 스레드 상태를 관리하고 어떤 스레드를 실행할지 결정

      (2) 여러 스레드가 공평하게 시스템 리소스를 사용하여 동작할 수 있도록 조정

      (3) 사전에 실행된 스레드의 순서를 결정하는 것이 아니라 우선 순위 및 대기 시간에 의해 결정하므로 실행할 때마다 결과는 다름

     

     ※ 스레드 우선 순위

      (1) 우선순위는 1에서 10으로 설정 가능하고 값이 높을수록 우선순위가 높음

      (2) 우선순위는 실행 대기중인 스레드에 상대적

    // 스레드 우선순위 필드
    public static final int MIN_PRIORITY = 1;  // 최소 우선 순위
    public static final int NORM_PRIORITY = 5; // 보통 우선 순위
    public static final int MAX_PRIORITY = 10; // 최대 우선 순위
    public class ThreadTest {
    
        public static void main(String[] args) {
            Thread thread1 = new Thread(group1, "thread1");
            thread1.setPriority(Thread.MIN_PRIORITY);   // 최소순위
            
            Thread thread2 = new Thread(group2, "thread2");
            thread2.setPriority(Thread.NORM_PRIORITY);  // 보통순위
            
            Thread thread3 = new Thread(group3, "thread3");
            thread3.setPriority(Thread.MAX_PRIORITY);   // 최고순위
            
            thread1.start();
            thread2.start();
            thread3.start();
        }
    }

     

    4. 구현

    class ThreadTest1 extends thread{
       // Thread 클래스를 상속 = Thread 클래스의 run()을 오버라이딩
       public void run(){
          /*
           * 작업 내용
           */
          for(int i=0; i < 5; i++) {
             System.out.println("thread"+i+":: "+getName());
          }
       }
    }
    class ThreadTest2 implements Runnable{
    	// Runnable 인터페이스를 구현 = Runnable인터페이스의 추상메서드 run()을 구현
        public void run(){
          /*
           * 작업 내용
           */
          for(int i=0; i < 5; i++) {
             System.out.println(Thread.currentThread().getName());  // 현재 실행중인 thread 이름 리턴
          }
       }
    }
    class ThreadExample1 {
       public static void main(String args[]) {
          ThreadTest1 t1 = new ThreadTest1();
          
          /*
          * Runnable 인터페이스에는 start() 메서드 없음 
          * -> 생성한 Runnable instance를 스레드 instance 생성할 때 파라미터로 넘겨서 스레드 사용
          */
          Runnable r = new ThreadTest2();
          Thread t2 = new Thread(r);
    
          /*
          * 한 번 사용한 스레드는 다시 재사용할 수 없음
          * 하나의 스레드에 start() 메서드는 한 번만 호출됨
          * 따라서, 새로운 스레드 작업이 필요하면 새로운 스레드를 생성한 후에 start() 메서드를 호출해야 함 
          */
          t1.start();  // 스레드 작업 시작
          t2.start();  // 바로 스레드가 실행되는 것은 아니고, 스케줄러가 정한 순서에 맞게 실행
       }
    }

     1) start() 메서드 호출
     2) start() 메서드에서 호출 스택 생성

     3) 호출 스택에서 run() 메서드 호출하여 스레드 작업 수행

     4) 스케줄러가 정한 순서에 따라 작업 수행

     

    5. 데몬 스레드

    class DemonThreadExample implements Runnable{
       static boolean autoSave = false;
    
       public static void main(String[] args) {
    
          Thread t = new Thread(new DemonThreadExample());
          t.setDaemon(true); // 데몬 스레드로 세팅
          t.start();
    
          for(int i=1; i<=33; i++){
             try{
                   Thread.sleep(1000);  // 1초 일시정지
                }catch(InterruptedException e){
                   e.printStackTrace();
                }
          
             System.out.println(i);
    
             if(i==3){
                autoSave = true;
             }
          }
          
          System.out.println("======= shutdown =======");
    
       } // main method end 
    
    
       @Override
       public void run() {
          while(true){
             try{
                   Thread.sleep(3 * 1000);  // 3초 일시정지
                }catch(InterruptedException e){
                   e.printStackTrace();
                }
    
             if(autoSave){
                autoSave();
             }
          }
       }
    
    
       private void autoSave() {
          System.out.println("------- auto saving -------");
       }
    }

     

     1) 메인 스레드드의 작업을 돕는 보조적인 역할을 수행하는 스레드

     2) 일반 스레드가 모두 종료되면 데몬 스레드는 강제적으로 자동 종료

     3) start() 메서드 실행 전에 setDaemon() 메서드를 실행해야 하고 그렇지 않으면 IllegalThreadStateException이 발생함

     

    6. 동기화

     1) 멀티 스레드 프로세스에서는 여러 개의 스레드가 작업을 하다가 동기화 문제가 벌어질 수 있음

      (예) 하나의 엑셀 문서를 2명이 공유하여 같이 작업할 때 a가 문서 작업하던 부분을 b가 고치면 작업 내용이 잘못 저장되거나 삭제될 가능성이 있다

     2) 특정 객체나 메서드에 lock을 걸어서 다른 스레드에 제어권이 넘어가도 데이터가 변경되지 않도록 처리해야 함

     

    class ThreadSynchronizedTest {
       public static void main(String args[]) {
    
          Runnable runnable = new SynchronizedTest();
          Thread t1 = new Thread(runnable);
          Thread t2 = new Thread(runnable);
    
          t1.start();
          t2.start();
       }
       
    }  // class end
    
    class SynchronizedTest implements Runnable {
       Account account = new Account();
    
       public void run() {
          while(account.balance > 0) {
             int money = (int)(Math.random() * 3 + 1) * 100;
             account.withdraw(money);
             System.out.println("balance:: " + account.balance);
          }
       }
    }  // class end
    
    class Account {
       int balance = 3000;
    
       public synchronized void withdraw(int money){  // synchronized:: 동기화 방지
          if(balance >= money) {
             try { 
                Thread.sleep(1000);
             } catch(Exception e) {
                e.printStackTrace();
             }
             
             balance -= money;
          }
       }
    }  // class end

     

     

     

     

    '과거 > Java' 카테고리의 다른 글

    SOLID원칙  (0) 2021.04.12
    엑셀 파일 읽기, 쓰기  (0) 2021.04.06
    Collections Framework  (0) 2021.03.11

    댓글