[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) {}
}
}
}
결과
입력하신 값은 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) {}
}
}
}
결과
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 %]
엑셀파일 다운로드 완료
[출처]
- 자바의정석 (저자: 남궁성)