스레드(Thread)

Yunsung·2025년 1월 8일
0
post-thumbnail

Java에서 Thread는 프로세스 내에서 독립적으로 실행되는 작업 단위를 의미합니다. 이 글에서는 스레드의 기본 개념, 사용방법, 동시성(comcurrency) 문제 및 이를 해결하는 방법을 예제를 통해 살펴보겠습니다.


1. 스레드란 무엇인가?

  • Program(프로그램): 실행 가능한 파일 (예: .exe, .jar 등).
  • Process(프로세스): 프로그램이 운영체제에 의해 메모리에 올라가 실행되는 단위. 독립된 메모리 공간을 사용함.
  • Thread (스레드): 프로세스 안에서 실제로 작업을 수행하는 실행 흐름(작업 단위).

즉, 스레드는 프로세스 내에서 독립적으로 실행되는 하나의 작업 흐름입니다.

🧠 예시로 이해하기
하나의 웹 브라우저(프로그램) 안에서
한 탭(프로세스)에서 여러 다운로드가 동시(스레드)에 진행된다.

“하나의 웹 브라우저(프로그램) 안에서, 한 탭(프로세스)에서 여러 다운로드가 동시에 진행(스레드)된다.”

참고:
크롬 같은 최신 브라우저는 탭마다 별도의 프로세스를 사용하는 멀티 프로세스 구조입니다.


Java에서 스레드의 주요 특징

  • Java 프로그램의 main 메서드는 기본적으로 하나의 스레드입니다.
  • 여러 스레드를 사용하면 동시에 여러 작업을 병렬로 처리할 수 있습니다.
  • 단, 스레드가 하나라도 살아있으면 프로그램이 종료되지 않습니다.

왜 스레드가 필요할까?

예를 들어, 여러 사용자가 동시에 로그인하는 웹서비스에서
스레드를 사용하지 않으면 한 명씩 순서대로 로그인 처리해야 하므로 느립니다.

하지만 스레드를 사용하면 동시에 여러 사람의 요청을 병렬로 처리할 수 있어 훨씬 빠릅니다.


2. 스레드 생성 방법

  • Runnable은 Java의 인터페이스로, 스레드에서 실행할 작업을 정의할 때 사용합니다.
  • Runnable 인터페이스에는 단 하나의 메서드인 run()이 있습니다. 이 메서드 안에 스레드가 실행할 코드를 작성합니다.
  • Thread 클래스는 Runnable 객체를 인자로 받는 생성자를 제공합니다.

예제: 기본 스레드 생성

public class Main {
	public static void main(String[] args) {
    	System.out.println("main thread start");
        
        Runnable run = new Runnable() {
        	@Override
            public void run() {
            	for (int i = 0; i < 10; i++) {
                	System.out.print(i + "\t");
                    try {
                    	Thread.sleep(1000); // 1초 대기
                    } catch (InterruptedException e) {
                    	e.printStackTrace();
                    }
                }
            }
        };
        
        Thread forThread = new Thread(run);
        forThread.start();
        System.out.println("main thread end");
    }
}

실행 순서

  1. 메인 스레드가 시작되며 "main thread start"를 출력합니다.
  2. Runnable 객체가 생성되고, 새로운 스레드가 시작됩니다.
  3. 메인 스레드는 "main thread end"를 출력하고 종료됩니다.
  4. 새로운 스레드는 0부터 9까지의 숫자를 1초 간격으로 출력 후 종료

3. 동시성과 동기화 문제

동시성 문제란?

여러 스레드가 하나의 자원(변수, 객체 등)을 동시에 접근할 때 문제가 발생할 수 있습니다.

🧠 예시
두 사람이 동시에 하나의 문서를 수정하면 내용이 꼬임
이런 걸 동시성 문제(concurrency issue)라고 합니다.

해결 방법: synchronized

synchronized 키워드를 사용하면
한 스레드가 자원을 사용하는 동안 다른 스레드는 기다렸다가 순차적으로 처리합니다.


4. 동시성 문제 예제

공유 자원을 사용하는 스레드

다음 예제는 공유 객체 Prt를 사용하는 두 개의 스레드 간 동시성 문제를 보여줍니다.

1)Prt 클래스

public class Prt {
    public void printChar(char charValue) {
        for (int i = 0; i < 10; i++) {
            System.out.print(charValue);
        }
        System.out.println();
    }
}

2) PrtThread 클래스

public class PrtThread implements Runnable {
    private Prt moniter;
    private char charValue;

    public PrtThread(Prt moniter, char charValue) {
        this.moniter = moniter;
        this.charValue = charValue;
    }

    @Override
    public void run() {
        synchronized (moniter) {
            for (int i = 0; i < 10; i++) {
                moniter.printChar(charValue);
            }
        }
    }
}

3) Main 클래스

public class PrtThreadApp {
    public static void main(String[] args) {
        Prt prt = new Prt();

        PrtThread charA = new PrtThread(prt, 'A');
        Thread thread01 = new Thread(charA);
        thread01.start();

        PrtThread charB = new PrtThread(prt, 'B');
        Thread thread02 = new Thread(charB);
        thread02.start();
    }
}

동작 과정

  1. thread01thread02는 동시에 prt.printChar()메서드를 호출하려 합니다.
  2. 동기화( synchronized ) 키워드가 없다면 두 스레드가 서로 충돌하여 출력 순서가 뒤섞입니다.
  3. synchronized (printer) 블록으로 감싸줌으로써 한 스레드씩 차례대로 접근하도록 합니다.
  4. synchronized가 없다면 출력이 ABABABA처럼 뒤섞일 수 있습니다.

실행 결과 (동기화 적용 후)

AAAAAAAAAA
BBBBBBBBBB

5. 정리

  • 스레드의 장점: 병렬 처리로 작업 시간을 줄일 수 있습니다.
  • 주의점: 동시성 문제를 피하기 위해 동기화 처리가 필요합니다.
  • 실제 사용: 동시성을 고려한 설계를 통해 안정적인 멀티스레드 프로그램을 구현할 수 있습니다.
profile
풀스택 개발자로서의 도전을 하는 중입니다. 많은 응원 부탁드립니다!!😁

0개의 댓글