Hyogi's Notebook

Day08 JAVA Studying

by 효기’s

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

 

 

멀티 스레드(작은 프로세스)

   독립적으로 동작함
   스레드란 프로세스 내에서 실행되는 세부 작업 단위이다.
   멀티 스레드란 하나의 프로세스에서 여러 개의 스레드가 ★병행적으로 처리되는 것을 말한다.

   실행중인 스레드가 하나라도 있다면 프로세스는 종료되지 않는다.

 

 

스레드의 생명주기

 


  스레드는 tread 객체가 생성되면 생명주기를 갖게 되는데 크게 5가지로 나누게 된다.


  new - 스레드가 만들어진 상태.
  Runnable - 스레드 객체가 생성된 후에 start() 메서드를 호출하면 runnable 상태로 이동하게 된다.
  Running - Runnable 상태에서 스레드 스케줄러에 의해 Running 상태로 이동하게된다.
  Blocked - 스레드가 다른 특정한 이유로 Running 상태에서 Blocked 상태로 이동하게 된다.
  Dead - 스레드가 종료되면 그 스레드는 다시 시작할 수 없게 된다.
   
 new 쓰레드라고 쓰는 즉시 쓰레드라고 할 수 있다

 

Thread 클래스로 직접 생성

Thread thread = new Thread (Runnable target);

 

구현 클래스run()을 재정의해서 스레드가 실행할 코드를 가지고 있어야 한다.

class Task implements Runnable {
	@Override
    public void run(){
    	// 스레드가 실행할 코드
    }

}

 

스레드에 전달하려면 Runnable 구현 객체를 생성한 후 Thread 생성자 매개값으로 Runnable객체를 전달한다.

Runnable task = new Task();

Thread thread = new Thread(task);

 

Runnable 익명 구현 객체를 매개 값으로 사용할 수 있다.

Thread thread = new Thread ( new Runnable() ) {
	@Override
    public void run(){
    	// 스레드가 실행할 코드
    }

}

작업 스레드를 실행하려면 start() 메소드를 호출해야한다.

thread.start();

 

Thread 자식 클래스로 생성

Thread의 자식 객체로 만드는데 Thread 클래스를 상속한 다음 run() 메소드를 재정의해서 스레드가 실행할 코드를 작성하고 객체를 생성한다.

 

public class WorkerThread extends Thread {

    @Override
    public void run() {
		// 스레드가 실행할 코드

    }
}

// 스레드 객체 생성
Thread thread = new WorkerThread();
thread.start();

 

익명 자식 객체 사용

Thread thread = new Thread(){

	@Override
    public void run(){
    
    // 스레드가 실행할 코드
    
    }


};
thread.start();

 

스레드 이름 변경

thread.setName("스레드 이름");

 

어떤 스레드가 실행하는지 확인

Thread thread = Thread.currentThread();
System.out.println(thread.getName());

 

스레드 상태

start() 메소드를 호출하면 실행 대기 상태(runnable)

run() 메소드를 실행하면 실행(running) 상태

run() 메소드가 종료하면 종료상태(terminated)

 

일시정지

sleep(long millis) = 주어진 시간동안 일시정지상태

join() = 스레드가 일시정지 상태

wait() = 스레드를 일시정지 상태

 

일시정지 상태 벗어남

interrupt() = 일시정지 상태일 경우, interruptedException 발생시켜 실행 대기상태, 종료상태로 만든다.

notify() = wait() 메소드로 인한 일시정지 상태 스레드를 실행 대기 상태로 만든다.

notifyAll() = wait() 메소드로 인한 일시정지 상태 스레드를 실행 대기 상태로 만든다.

 

실행 대기로 보냄

yield() = 실행 상태에서 다른 스레드에게 실행을 양보하고 실행 대기 상태가 된다.

 

스레드 동기화

스레드가 사용중인 객체를 다른 스레드가 변경할 수 없도록 하려면 스레드 작업이 끝날 때까지 객체에 잠금을 건다.

자바는 동기화 메소드와 블록을 제공한다.

 

스레드 A가 실행될때 스레드 B는 동기화 메소드, 블록을 실행 불가능하고 일반 메소드는 실행이 가능하다.

 

동기화 메소드 및 블록 선언

public synchronized void method() {

// 단 하나의 스레드만 실행하는 영역 (동기화 메소드)

}

동기화 메소드 실행하면 객체의 잠금이 일어난다.

 

일부 영역을 실행할때만 객체 잠금하는 방법

public void method(){

// 여러 스레드가 실행할 수 있는 영역


synchronized(공유객체){

// 단 하나의 스레드만 실행 하는 영역
}
//여러 스레드가 실행할 수 있는 영역
}

 

wait와 notify() 를 이용한 스레드 제어

두개의 스레드를 교대로 번갈아가며 실행할 때

자신이 작업이 끝나면 notify() 메소드로 상대방 스레드를 일시 정지 상태에서 풀어주고(실행대기 상태로 만듬)

자신은 wait() 메소드를 호출하여 일시 정지 상태로 만들면 된다.

 

스레드의 안전 종료

스레드를 즉시 종료할때 조건 이용 방법과 interrupt() 메소드 이용 방법이 있다.

 

interrupt() 메소드는 스레드가 일시 정지 상태일때 예외처리를 통해 run()메소드를 정상 종료 시킬 수 있다.

 

데몬스레드

데몬 스레드는 주 스레드의 작업을 돕는 보조적인 역할을 수행하는 스레드이다.

주 스레드가 종료되면 데몬 스레드도 따라서 자동으로 종료된다.

 

스레드 풀

병렬 작업 증가로 인한 스레드의 폭증을 막으려면 스레드풀을 사용해야한다.

 

작업 처리에 사용되는 스레드를 제한된 개수만큼 정해놓고

작업 큐에 들어오는 작업들을 스레드가 하나씩 맡아 처리하는 방식이다. 

작업처리가 끝난 스레드는 다시 작업 큐에서 새로운 작업을 가져와 처리한다.

 

스레드 풀 생성

java.util.concurrent 패키지에 제공

ExecutorService executorService = Executors.newCashedThreadPool();

초기수 0개, 작업 개수 최대 5개 스레드 생성시켜 작업 처리한다.

특징은 생성된 스레드를 제거하지 않는다.

 

ExecutorService executorService = Executors.newFixedThreadPool(5);

초기수 0개 코어수 3개, 최대수 100개인 스레드풀을 생성

추가된 120초 동안 놀고 있을 경우 해당 스레드를 풀에서 제거한다.

 

스레드 풀 종료

스레드 풀의 스레드는 데몬 스레드가 아니기 때문에 main 스레드가 종료되더라도

작업을 처리하기 위해 계속 실행상태이다.

모든 스레드를 종료하려면 ExecutorService의 두 메소드 중 하나를 실행해야한다.

 

shutdown() = 현재 처리중인 작업 뿐아니라 작업 큐에 대기하고 있는 모든 작업을 처리 후 스레드를 종료시킨다.

shutdownNow() = 현재 작업중인 스레드를 interrupt해서 작업을 중지시키고 스레드를 종료시킨다(바로 강제종료)

 

작업 생성과 처리요청

 

Runnable 익명 구현 객체

new Runnable() {
    @Override
    public void run(){

    // 스레드가 처리할 작업 내용

    }
}

Callable 익명 구현 객체

new Callable<T>(){

	@Override
    public T call() throws Exception {
    	// 스레드가 처리할 작업 내용
        return T;
    
    }


}

execute(Runnable command) = Runnable을 작업 큐에 저장, 작업 처리 결과를 리턴하지 않음.

submit(Callable<T> task) = Callable을 작업 큐에 저장, 작업 처리 결과를 얻을 수 있도록 future을 리턴.

'Studying > JAVA' 카테고리의 다른 글

JAVA 문자열타입: 다양한 관리방법  (7) 2023.07.26
JAVA 최댓값 최소값 쉽게 구하기  (7) 2023.07.17
Day07 JAVA Studying  (19) 2023.07.11
Day06 JAVA Studying  (1) 2023.07.10
Day05 JAVA Studying  (0) 2023.07.07

블로그의 정보

감성 개발자 효기

효기’s

활동하기