[Java] 12. Multi-Thread(멀티쓰레드)란?


이전 쓰레드 포스팅에 이어서 멀티쓰레드에 대해서 부가 설명 및 예제코드 포스팅이다.

멀티쓰레드는 멀티프로세스는 PC에서 프린트 등 인쇄 등을 백그라운드로 두고 자기 할일은 하는 것처럼 사용되거나 오래 걸리는 작업이나 I/O 요청을 멀티쓰레드를 이용해서 비즈니스 로직을 처리하는 경우가 있다. 흔히 개발 할때 대용량 파일처리나 엑셀 다운로드 경우가 있다.



1. 멀티스레드 I/O 블럭킹 예제

멀티쓰레드 I/O 블럭킹 예제에 앞서 아래 설명을 간단하게 보고 넘어가자. 더 자세한 내용은 [CS] [Blocking I/O, Non-blocking I/O] X [Sync, Async]에서 확인하면 될 듯 하다.


1) I/O

-I/O란 데이터의 입력(Input)과 출력(Output)을 말한다. I/O는 파일 입출력뿐만 아니라 이기종간 네트워크를 통해서 데이터를 주고 받는것도 I/O라 칭한다.

2) Blocking/Non-blocking

  • Blocking/Non-blocking : 호출되는 I/O 함수가 바로 리턴하느냐 아니면 제어권을 가져가서 block 하느냐 차이이다.
  • Blocking I/O : I/O가 호출되면 제어권을 가져가서 어플리케이션이 멈춤
  • Non-blocking I/O : 어플리케이션에서 I/O를 호출해도 어플리케이션이 제어권을 가지므로, I/O가 완료될 때까지 대기하지 않고 작업을 처리한다.



싱글쓰레드 Blocking I/O

아래 어플리케이션이 showInputDialog 에게 I/O 요청하는 순간 제어권이 I/O에게 넘어가고 어플리케이션은 대기한다. 입력창에서 확인버튼을 눌러야 I/O 결과와 제어권이 어플리케이션에게 넘어가서 for문을 처리한다.

쓰레드가 입출력(I/O)처리를 위해 기다리는 것을 I/O Blocking이라고 한다.


public class ExIOBlockSingleThread {

    public  static void main(String... args) throws Exception {
        //1) I/O 요청
        String input = JOptionPane.showInputDialog("입력해주세요.");
        System.out.println("입력하신 값은 " + input+ " 입니다.");

        //2) 어플리케이션 작업
        for (int i=10; i>0; i--) {
            System.out.println(i);
            try {
                Thread.sleep(1000);
            } catch (Exception e) {}
        }
    }
}


multi-thread_ex1-s1


결과

입력하신 값은 I/O 요청 결과 리턴 입니다.
10
9
8
7
6
5
4
3
2
1



멀티쓰레드 Non-Blocking I/O

멀티쓰레드로 어플리케이션 작업을 진행하고 I/O 요청을 했다. 입력창에서 확인 버튼을 안눌러도
기존 멀티쓰레드와 showInputDialog I/O 요청은 각자의 작업을 진행하는 것을 볼 수 있다.


public class ExIONonBlockMultiThread {

    public  static void main(String... args) throws Exception {
        //1) 멀티쓰레드로 어플리케이션 작업
        WorkIONonBlockMultiThread t = new WorkIONonBlockMultiThread();
        t.start();

        //2) I/O 요청
        String input = JOptionPane.showInputDialog("입력해주세요.");
        System.out.println("입력하신 값은 " + input+ " 입니다.");
    }
}

class WorkIONonBlockMultiThread extends Thread {
    @Override
    public void run() {
        for (int i=10; i>0; i--) {
            System.out.println(i);
            try {
                Thread.sleep(1000);
            } catch (Exception e) {}
        }
    }
}


multi-thread_ex1-s2


결과

10
9
8
7
6
    
4
3
2
1
입력하신 값은 I/O 요청 결과 리턴 입니다.



간단한 멀티쓰레드 추가 예제

대충 아래와 같이 고민해서 사용해보자.

public class ExMultiThread {

    public static void main(String... args) {

        ExcelFileThread excel = new ExcelFileThread();
        excel.excelFileDownload();

        System.out.println("사용자 요청 로직 시작");
        for(int i=0;i<10;i++) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("사용자 요청 로직 종료");
    }
}

class ExcelFileThread extends Thread {

    public void excelFileDownload () {
        super.start();
    }

    public void run () {

        System.out.println("엑셀파일 다운로드 시작");

        for(int i=0;i<15;i++) {
            System.out.println("    >> 엑셀 다운로드 상태=[ "+ (i * 100 / 15) +" %]");
            //System.out.print("...");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        System.out.println("엑셀파일 다운로드 완료");

    }
}

결과

사용자 요청 로직 시작
엑셀파일 다운로드 시작
    >> 엑셀 다운로드 상태=[ 0 %]
    >> 엑셀 다운로드 상태=[ 6 %]
    >> 엑셀 다운로드 상태=[ 13 %]
    >> 엑셀 다운로드 상태=[ 20 %]
    >> 엑셀 다운로드 상태=[ 26 %]
    >> 엑셀 다운로드 상태=[ 33 %]
    >> 엑셀 다운로드 상태=[ 40 %]
    >> 엑셀 다운로드 상태=[ 46 %]
    >> 엑셀 다운로드 상태=[ 53 %]
    >> 엑셀 다운로드 상태=[ 60 %]
사용자 요청 로직 종료
    >> 엑셀 다운로드 상태=[ 66 %]
    >> 엑셀 다운로드 상태=[ 73 %]
    >> 엑셀 다운로드 상태=[ 80 %]
    >> 엑셀 다운로드 상태=[ 86 %]
    >> 엑셀 다운로드 상태=[ 93 %]
엑셀파일 다운로드 완료


[출처]

  • 자바의정석 (저자: 남궁성)