본문 바로가기
쿤즈 Dev/Java

[Java] 멀티 스레드 (Multi-Thread) 기본 개념

by :)Koon 2023. 10. 6.

자바(Java) 프로그래밍을 이용해서 서비스를 만들고자 할 때, 반드시 등장하는 부분이 바로 동시성(Concurrency)이다. 동시성 문제는 다양하게 해결이 가능하며, 이때 다루는 개념이 바로 멀티 스레드다.

이번 포스팅에서는 멀티 스레드에 대해서 알아보자.


멀티 스레드 Multi-Thread

멀티 스레드는 하나의 프로그램이 동시에 여러 작업을 수행할 수 있는 기술을 의미한다. 이는 프로그램의 성능 향상과 동시성(Concurrency) 문제를 다루는데 도움이 된다. 멀티 스레딩의 기본 개념은 다음과 같다.


스레드와 멀티 스레드

스레드는 프로세스 내에서 실행되는 최소 단위의 작업이다. 하나의 프로세스는 여러 개의 스레드를 가질 수 있으며 각각의 스레드는 독립적으로 실행된다.

멀티 스레드는 여러 스레드가 동시에 실행되는 것처럼 보이도록 하는 것을 목적으로 한다.

 

멀티 스레드의 이점

성능향상

여러 작업을 동시에 수행함으로써 전체적인 프로그램의 성능을 향상 시킬수 있다.

자원 공유

스레드는 프로세스 내의 메모리를 공유하므로, 데이터를 쉽게 주고 받을 수 있다.

응답성 향상

여러 작업을 병렬로 처리하므로 사용자에 대한 빠른 응답이 가능하다.

 

스레드 생명주기

스레드는 일반적으로 생성, 실행, 대기, 종료 등의 단계를 거친다.

생성은 스레드 객체가 생성됨을 말한다.

실행은 'start()' 메서드를 호출하여 스레드가 실행됨을 의미한다.

대기는 다른 스레드의 실행을 기다리거나 특정 조건을 기다린다.

종료는 작업이 완료되면 스레드가 종료됨을 의미한다.

 

스레드 동기화

멀티 스레드에서 여러 스레드가 공유 자원에 동시에 접근할 수 있으므로 데이터의 일관성을 유지하기 위해 스레드 동기화가 필요하다.

'synchronized' 키워드 혹은 'java.util.concurrent' 패키지의 동기화 메커니즘을 사용하여 동기화를 구현한다.

 

공유 자원과 경쟁 조건

여러 스레드가 공유 자원에 동시에 접근할 때 경쟁 조건(Race Condition)이 발생할 수 있다. 이는 예상치 못한 결과를 초래할 수 있으므로 주의가 필요하다.

 

스레드 풀 Thread Pool

스레드를 직접 생성하고 관리하는 것은 부담스러운 일이다. 그래서 스레드 풀은 스레드를 효율적으로 관리하여 여러 작업을 처리하는 데 도움을 준다.

 

멀티 스레드

자바에서는 'Thread' 클래스를 사용하여 스레드를 생성하고 'Runnable' 인터페이스를 구현하는 방법도 제공된다. 또한 'java.util.concurrent' 패키지에서 스레드 풀과 관련된 유틸리티 클래스를 제공한다.


멀티 스레드는 복잡성을 동방하지만, 올바르게 구현하면 성능 향상과 동시에 문제를 효과적으로 다룰 수 있다. 그러나 스레드를 사용할 때는 주의 깊은 설계와 동기화에 대한 이해가 필요하며, 안정성을 고려하여 프로그래밍해야 한다.


스레드를 만드는 간단한 예제

스레드를 만드는 방법은 크게 두 가지로 나뉜다. 첫 번째는 'Thread' 클래슬르 직접 상속하거나 'Runnable' 인터페이스를 구현하여 스레드를 생성하는 방법이다. 두 번째는 'ExecutorService' 인터페이스를 사용하여 스레드 풀을 생성하는 방법도 있다.


Thread 클래스 또는 Runnable 인터페이스 사용

먼저 'Thread' 클래스를 상속받아서 스레드를 만드는 방법을 알아보자.

class ThreadA extends Thread{
    @Override
    public void run() {
        for(int i=0; i<10; i++) {
            System.out.println("This is ThreadA.");
        }
    }
}

'Thread' 클래스를 상속받을 때에는 'run()' 메서드를 오버라이드 하여 동작을 구현해 준다.

class RunnableA implements Runnable {
    @Override
    public void run() {
        for(int i=0; i<10; i++) {
            System.out.println("This is RunnableA.");
        }
    }
}

'Runnable' 인터페이스를 구현할 때에도 마찬가지로 'run()' 메서드를 오버라이드하여 반드시 구현해 주도록 한다.

이제 이 두 스레드를 실행해 보자.

public class ThreadTest {
    public static void main(String[] args) {
        ThreadA threadA = new ThreadA();
        threadA.start();

        Thread threadB = new Thread(new RunnableA());
        threadB.start();
    }
}

'threadA' 인스턴스는 Thread 클래스를 상속받았기 때문에 바로 'start()' 메서드를 이용해 스레드를 실행한다. 반면 'threadB' 인스턴스는 스레드를 생성할 때 'RunnableA' 클래스를 이용해서 새로운 인스턴스를 만들어주고 그 인스턴스를 받아서 생성한다. 이것이 'Thread'와 'Runnable'의 차이다.

 

ExecutorService 스레드풀 사용

이번에는 스레드 풀을 사용해서 스레드를 실행시켜 보는 예제를 만들어 보자.

public class ThreadTest {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(5);
        executorService.execute(new RunnableA());
        executorService.shutdown();
    }
}

ExecutorService 인스턴스를 만들어준다. 이때 스레드풀에는 5라는 값을 입력했다. 이는 재사용 가능한 스레드들이 5개가 존재한다는 의미다.

'executorService' 인스턴스의 'execute()' 메서드는 인자로 'Runnable' 클래스의 인스턴스를 받게 되어 있다. 따라서 위에서 만든 'RunnableA' 클래스의 인스턴스를 생성해서 넣어준다. 실행결과는 똑같다.

 

이로써 스레드를 만들 수 있게 되었고 사용할 수 있게 되었다. 물론 실무에서는 더 다양한 클래스들을 사용하여 구현하고 대부분은 스레드 풀을 이용한다.


멀티 스레드는 언제 사용할까

멀티 스레드는 주로 다음과 같은 상황에서 사용된다.

 

병렬성이 필요한 작업

멀티 스레드는 여러 작업을 동시에 수행할 수 있다. 이는 CPU 자원을 효과적으로 활용하여 작업을 병렬로 처리하는 데 도움이 된다. 예를 들어서 복잡한 계산 작업, 그래픽 처리, 네트워크 통신 등이 있다.

 

응답성 향상

사용자 인터페이스 응답성을 향상시키기 위해 멀티스레드를 사용한다. 긴 작업을 백그라운드 스레드에서 처리하여 메인 스레드가 블록 되지 않도록 할 수 있다.

 

동시성 문제 해결

여러 스레닥 동시에 실행되는 경우, 공유 자원에 대한 동시성 문제를 해결하기 위해 멀티 스레드를 사용한다. 스레드 간의 데이터 공유를 효율적으로 관리하려면 적절한 동기화가 필요하다.

 

성능 향상

멀티 스레드를 사용하면 여러 작업을 병렬로 처리함으로써 전체적인 프로그램의 성능을 향상시킬 수 있다.

 

대기시간 최소화

입출력(IO) 작업에서 멀티 스레드를 사용하면 한 스레드가 대기하는 동안 다른 스레드가 작업을 수행하여 대기 시간을 최소화할 수 있다.

 

데이터 다운로드 또는 처리

네트워크에서 대량의 데이터를 다운로드하거나, 대용량 파일을 처리하는 작업에서 사용하면 시간을 단축할 수 있다.

 

스레드 풀 활용

스레드 풀을 사용하면 스레드의 생성 및 소멸에 따른 오버헤드를 줄이고, 여러 작업을 효율적으로 관리할 수 있다.


이번 포스팅에서는 스레드와 멀티 스레드에 대해서 알아보았다. 현재는 정말 많은 곳에서 스레드를 사용하고 있고 멀티스레드를 사용하여 효율적으로 프로그래밍을 하고 있다. 여기까지가 기본 개념으로 알아두고 넘어가자.

댓글