Tiny Bunny [JAVA] 멘토씨리즈 자바_SECTION.18 - 솜님의 블로그
솜님의 블로그
작성일
2024. 7. 30. 02:17
작성자
겨울솜사탕

프로세스(process)와 스레드(thread)

동시에 두 가지 이상의 작업을 처리하는 것을 '멀티태스킹'이라고 한다.

컴퓨터에서 멀티태스킹을 위한 두 가지 도구가 있는데, 프로세스와 스레드이다.

 

프로그램은 파일이 존재하지만 아직 메모리에 올라가 있지 않은 상태를 의미한다.

(실행되지 않은 코드의 집합)

프로그램을 실행하는 순간 메모리에 올라가고 동작하게 되는데 이 상태의 프로그램을 프로세스라고 한다.

 

프로그램이 실행되면 메모리에 적재되고, 프로세스가 된다.

프로세스는 독립적으로 메모리에 등록되므로 여러 개의 프로그램을 동시에 실행할 수 있게 된다.

 

이러한 프로세스 내부에 존재하며 실행 흐름을 나타내는 것스레드라고 한다.

하나의 프로그램 안에서 다양한 작업을 동시에 하기 위해 스레드가 각자 독립적으로 존재하여 일을 수행하는데,

하나의 프로세스는 적어도 한 개의 스레드를 가진다.

 

 

스레드의 사용

스레드를 생성하는 방법

- Thread 클래스를 상속하여  run() 메서드 구현
- Runnable 인터페이스 구현

 

스레드는 클래스에 Thread를 상속받은 뒤, Thread가 가지고 있는 run() 메서드를 사용해 생성한다.

만약 상속이 어려운 경우엔 Runnable 인터페이스를 상속해 구현할 수 있다.

 

 

Thread 클래스 상속

스레드는 run() 메서드에서 구현하지만 클래스를 실행하기 위해서는 start() 메서드를 호출해야 한다.

▼예제

class MyThread extends Thread{
	@Override
    public void run(){
    	int sum = 0;
        for(int i = 0; i<10; i++){
        	sum = sum + (i+1);
        }
        
        System.out.println("sum = " + sum);
        String threadName = Thread.currentThread().getName();
        System.out.println("현재 스레드 이름 : " + threadName );
    }

}

public class SumMain{
	public static void main(String[] args){
		MyThread th = new My Thread();
        th.start();
    }

}

 

* 실행 결과

- sum = 55

- 현재 스레드 이름 : Thread-0

스레드 동작을 위해 run() 메서드를 구현하고,

String threadName가 선언되어 있는 코드에서 별도로 스레드 이름을 지정해주지 않으면 시스템에서 정의한다.

스레스를 시작할 때는 start() 메서드를 호출해서 사용한다.

 

 

Runnable 인터페이스 상속

자바는 다중 상속이 불가하기 때문에 기존에 상속되어 있는 클래스를 스레드로 만들려면 Runnable 인터페이스를 상속하여 구현할 수 있다.

Thread th = new Thread(Runnable을 상속한 인스턴스);

Thread 클래스를 선언하면서 Runnable을 상속한 클래스를 선언하여 매개변수로 넘겨줘야 한다.

이유는 실제 Thread 클래스가 스레드를 실행하는 주체이고, Runnable 인터페이스를 상속한 클래스는 실행 코드를 지닌 객체이기 때문이다.

 

▼예제

// Runnable을 상속
class whiteFlag implements Runnable{
	@Override
    public void run(){
    	while(true){
        	System.out.println("백기 올려");
        }
    }
}

// 스레드 메인
public class RunnableExample{
	public static void main(String[] args){
    	Thread write = new Thread(new whiteFlag());
        write.start();
    }
}

 

* 실행 결과 : 

백기 올려

백기 올려

백기 올려

.....

 

Thread에 이름 부여하기

스레드는 다중 실행이 가능하다.

따라서 현재 진행 중인 스레드가 어떤 작업을 하는지 알기 위해 이름을 부여할 수 있다.

스레드는 'Thread-n' 이라는 이름으로 자동 생성되는데,

다른 이름으로 설정하고 싶다면 Thread 클래스의 setName() 메서드를 변경한다.

 

 

멀티 스레드

여러 개의 스레드를 이용해 동시게 작업을 수행할 수 있는데, 이것이 멀티 스레드이다.

같은 시간에 서로 다른 독립적인 스레드가 일을 처리하는 것을 비동기 작업이라고 한다.

 

 

 

스레드 동기화

멀티 스레드 프로그램이 실행될 때 다수의 스레드가 하나의 데이터를 공유하면서 스레드 간 경쟁이 일어날 수 있다.

이때, 간혹 스레드의 순서가 맞지 않을 경우 비정상적인 동작이 일어날 수 있다.

이러한 오류를 방지하기 위해 여러 스레드가 하나의 공유 데이터에 동시에 접근하지 못하도록 스레드의 실행을 제어하는데, 이를 '스레드 동기화'라고 한다.

 

 

스레드 동기화 처리

멀티 스레드에서 단 하나의 스레드만 처리할 수 있는 영역을 '임계 영역'이라고 한다.

하나의 스레드가 이 영역에 진입시 락을 걸어 다른 스레드가 수행되지 못하게 하고, 작업이 종료되면 락을 풀게 된다.

이것을 '동기화 처리'라고 한다.

 

동기화 처리는 synchronized 키워드를 사용한다.

 

메서드 동기화 처리

메서드 이름 앞에 synchronized 키워드를 사용하면 해당 메서드 전체를 동기화 처리 O

// 동기화 방법
public synchronized void add()...

// 예시
public synchronized void addMoney(int money){
	....
}

 

블록 동기화 처리

메서드 동기화의 경우 메서드 전체를 동기화하기 때문에 처리 시간이 길어져 성능에 영향을 미치는 단점이 있다.

이러한 이유로 특정 영역만 동기화 처리를 할 수 있는데, 이를 '블록 동기화 처리'라고 한다.

이는 실제 실행하는 스레드의 일부분을 동기화하여 처리하는 방법을 말한다.

// 블록 동기화 방법
synchronized (객체명) ...

// 예시
@Ovrride
public void run(){
	synchronized (b){
    	...
    }
    ...
}

 

 

 

스레드 상태

스레드 상태에 따라 6개의 타입으로 나뉜다

 

 

NEW와 RUNNABLE, TERMINATED

처음 스레드 생성되면 스레드는 NEW 상태가 된다.

생성 이후 start() 메서드 실행하면 메서드는 RUNNABLE 상태로 변하고, 스레드가 종료되면 TERMINATED 상태가 된다.

 

 

스레드 WAIT

필요에 의해 스레드를 잠시 멈춤 상태로 두는 것을 의미한다.

 

sleep

sleep(int mils) 메서드는 주어진 시간 동안 스레드를 정지시키는 메서드이다.

모든 스레드를 대기시키며, 주어진 시간이 지나면 풀리게 된다.

 

wait()와 notify()

wait() 메서드는 스레드를 대기시키고,

notify() 메서드는 대기 중인 스레드를 다시 동작시킬 때 사용한다.