ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 자바기초 4 [쓰레드 & 쓰레드 풀 ]
    OOP & JAVA 2021. 6. 30. 18:30

    1. 프로세스와 쓰레드

    운영체제는 여러 프로세스[어플리케이션]을 동작시키고 프로세스는 여러 쓰레드를 운영한다

    프로세스간은 독립적이지만 쓰레드는 프로세스 단위로 묶여있기 때문에 쓰레드의 오류는 

    어플리케이션의 비정상적 종료를 유도 할 수 있다.

     

    쓰레드들은 cpu 스케줄러에 의해 실행 순서가 정해지고  run코드의 부분 부분이 실행된다.

    부분 부분이 실행되는 과정에서 실행상태와 대기상태를 오가며 마침내 종료된다.

     

     

    프로세스와 쓰레드의 자세한 설명

    https://easycodediary.tistory.com/56?category=924225 

     

    [ 운영체제 ] 5. 스레드 와 프로세스

    프로세스 : 프로그램을 메모리 상에서 실행중인 작업 스레드 : 프로세스 안에서 실행되는 여러 흐름 단위 1. 프로세스와 스레드의 차이 데이터 접근 프로세스 간에는 각 프로세스의 데이터 접근

    easycodediary.tistory.com

     

    2. 쓰레드 생성 및 실행

     

    스레드는 runnable 인터페이스를 이용하는 방법과 스레드를 상속받아 이용하는 방법이 있다.

    • Thread 상속
      • 조금 더 편함 , but Thread 클래스를 상속 받기 때문에 다중 상속 불가
    • Runnable 구현
      •  다중상속을 고려한다면 인터페이스로서 ruunable 이용이 좋음

     

    // Runnalbe 이용
    
    //Runnable  인터페이스 구현 클래스 생성
    class Task implements Runnable{
    @override
    publi void run(){
    	
        }
    }
    
    //쓰래드 생성 및 실행
    Runnalbe task = new Task();
    Thread thread = new Thread(task);
    thread.start();

     

     

    //Thread 클래스 상속
    
    public  class WorkerThread extends Thread{
    @override
    public void run(){
    
    	}
    }
    
    Thread thread = new WorkerThread();
    thread.start();

     

    3. 동기화 및 협업

    : 동기화란 쓰레드간 공유하는 정보에 대해서 실행순서에 의해 정보가 오염되지 않도록 한 쓰레드가 처리를 마쳤을때 다른 쓰레드가 접근할 수 있게하는 방식을 의미한다.

     

    쉽게말해 A 스레드가 공유자원을 사용하고 있는데 그 사이 B가 공유자원에 값을 바꿔놓을 가능성을 배제하는 것입니다.

     

    동기화에 대한 자세한 설명은 위에 제공한 프로세스와 스레드 링크를 참고해주세요

     

    공유되는 객체에대한 사용제한을 위해 동기화 메소드( public synchronized void 함수이름(){} )를 이용 하거나 동기화 블록을 통해서 적용 시킬수 있다.

     

    wait(본 쓰레드르 잠깐 멈춤) , notify ( 일시정지 상태의 다른 쓰레드를 실행대기로 만들어줌) 와 같이 사용할때 큰 효용을 얻을 수 있다.

     

    4.  쓰레드 종료

    -  stop 플래그 이용

    // Thread class
    public class MyThread extends Thread{
    private boolean stop;
    
    public void setStop(boolean stop){
    	this.stop = stop;
    }
    
    public void run(){
    while(!stop){
    	//샐행문	
            }
    	}
    
    }
    
    // Main Thread
    public class StopFlagExample{
    	 puboic static void mian(){
       	MyThread myThread = new MyThread();
    
            myThread.start();
            try {
                Thread.sleep(1500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            myThread.setStop(true);
         
         }
    }

     

    - interrupt() 메소드 이용

    : interrupt 메소드는 스레드가 일시정지 상태가 되면 예외를 발생시켜 해당 쓰레드를 정지 시킨다.

    따라서 반드시 일시정지 상태를 만들어 주어야 한다.

     

    //쓰레드 클래스
    public class MyThread extends Thread {
    
        private boolean stop;
    
        public void setStop(boolean stop) {
            this.stop = stop;
        }
    
        public void run() {
            while (true) {
                try {
                    System.out.println("실행중");
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    break;
                }
            }
        }
    }
    
    //Main 클래스
    
     MyThread myThread = new MyThread();
    
            myThread.start();
            try {
                Thread.sleep(1500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    
            myThread.interrupt();

     

     

    5.  쓰레드 풀

    스레드풀은 병렬 작업이 많아지고 동시에 쓰레드 작업이 급증해서 어플리케이션 성능이 기하급수적으로 떨어짐을 방지하기 위한 기능으로 쓰레드 생성 전부터 미리 스레드의 개수를 정하여 만들어 놓고 작업 큐에서 할당 받은 작업을 쓰레드 에서 작업하며 완료 됬을때 새로운 작업을 작업큐에서 할당받는 식의 구조를 갖는다.

     

     

    // 두가지 방식으로 생성 가능
    ExecutorService executorService = Executors.newCachedThreadPool();
        
    ExecutorService executorService2 = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
    
    // 작업 생성1 [ 요청 타입 없음 ]
    Runnable task = new Runnable() {
                @Override
                public void run() {
                    // 실행 내용
                }
            };
    
    // 작업 생성2 [ 요청 타입 있음 ]
    Callable<T> task = new Callable<T>() {
                @Override
                public T call() throws Exception {
    
                    return T;
                }
            };
            
            
    //작업 처리 요청 방법 2개 [submit이 오류났을때 쓰레드 재활용 함 ] 
    executorService.execute(runnable);
    executorService.submit(runnable);
    
    
    
    // 스레드 풀 종료
     executorService.shutdown();

     

     

    리턴값에 대한 통보

     

    :  future.get 메소드는 브로킹 특징을 가지므로 같은 클래스 내 다른 작업을 막기때문에 이를 주의해서 배치해야한다.

    ->새로운 스레드를 만들거나  ,  스레드 풀의 스레드가 호출  하게 끔 만드는 것이 좋다.

     

     

    < 새로운 쓰레드 생성 >
    
    Future future = executorService.submit(runnalbe);
    //or 리턴 타입 있을댄 runnalbe 대신 callble 객체
    
     new Thread(new Runnable() {
                @Override
                public void run() {
                    // 실행 내용
    
                    try {
                        future.get();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();
            
            
    executorService.shutdown();

     

     

    < 새로운 쓰레드 생성 >
    excutorService.submit(new Runnable() {
                @Override
                public void run() {
                    // 실행 내용
    
                    try {
                        future.get();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            });
            
    

     

     

    댓글

Designed by Tistory.