본문 바로가기
멀티캠퍼스 풀스택 과정/Java의 정석

자바의 정석10-2 싱글쓰레드와 멀티쓰레드, 쓰레드의 I/O 블락킹

by 이쟝 2022. 1. 12.

싱글쓰레드와 멀티쓰레드

싱글쓰레드 프로세스(main)와 멀티쓰레드 프로세스(t1,t2)의 비교

 

두 개의 쓰레드로 작업한 시간이 싱글쓰레드로 작업한 시간보다 더 걸리게 되는데 그 이유는 쓰레드간의 작업전환(context switching)에 시간이 걸리기 때문

-> 단순히 CPU만을 사용하는 계산작업은 오히려 멀티쓰레드보다 싱글쓰레드로 프로그램하는 것이 더 효율적!!

예제)  ' - ' 를 출력하는 작업과 ' | '를 출력하는 작업을 하나의 쓰레드가 연속적으로 처리하는 시간을 측정하는 예제(싱글쓰레드 프로세스)

 

class Ex13_2 {
	public static void main(String[] args) {
		long startTime = System.currentTimeMillis();
		
		//1번 작업 수행
		for(int i=0; i < 100; i++)
			System.out.printf("%s", new String("-"));
		
		System.out.println("소요시간1: " + (System.currentTimeMillis() - startTime));
		
		//2번 작업 수행
		for(int i=0; i < 100; i++) 
			System.out.printf("%s", new String("|"));
		
		System.out.println("소요시간2: " + (System.currentTimeMillis() - startTime));
	}
}

 

더보기

수행시간을 측정하기 쉽게 "-"대신 new String("-")를 사용해서 수행속도를 늦췄다. 

 

<출력값>

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------소요시간1: 115
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||소요시간2: 151

 

예제2) 예제1을 멀티쓰레드러 변형

 

class Ex13_3 {
    public static long startTime = 0; // main 메서드 안에 있으면 ThreadEx4_1이 사용할 수 없음

	public static void main(String[] args) {
		ThreadEx4_1 th1 = new ThreadEx4_1();  // Thread를 상속한 ThreadEx4_1 객체 생성
		th1.start();//2번 작업 수행
		startTime = System.currentTimeMillis();
		
        //1번 작업 수행
		for(int i=0;i<100;i++) 
			System.out.printf("%s", new String("-"));
		
		System.out.println("소요시간1: " + (System.currentTimeMillis() - startTime));
		}
}
//2번 작업 수행
class ThreadEx4_1 extends Thread {  
	public void run() {
		for(int i=0; i<100; i++) 
			System.out.printf("%s", new String("|"));
		
		System.out.println("소요시간2: " + (System.currentTimeMillis()-Ex13_3.startTime));
	}
}

 

더보기

<출력값>

----------||-------------------||||||||||||---||||||||---------------------|||------|||||||||||||----|-----||||||||||||||-----|||||||-------------------------------------------------------------------------------------------------------|||--||||-----|||--------------||----------------------------------------||||||||---------------------------------------------------------------||||||||||||||||||||||||||||||||||||||||||||||소요시간2: 107
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||소요시간2: 124

 

싱글쓰레드와 비교해서 번갈아가면서 실행 되었다. 

싱글쓰레드보다 더 많이 시간이 걸린 이유: 쓰레드간의 작업전환시간이 소요(1), 한 쓰레드가 화면에 출력하고 있는 동안 다른 쓰레드는 출력이 끝나기를 기다리는 대기시간(2) 


쓰레드의 I/O 블락킹(blocking)

- 입출력시 작업 중단 되는 것 -> I/O 블락킹

 

싱글쓰레드 프로세스(위)와 멀티쓰레드 프로세스(아래)의 비교

-> 만일 사용자로부터 입력 받는 작업화면에 출력하는 작업하나의 쓰레드로 처리한다면 첫 번째 그래프처럼 사용자가 입력을 마칠 때까지 아무 일도 하지 못하고 기다려야함!!!

 

-> 두개의 쓰레드로 처리하면 사용자의 입력을 기다리는 동안 다른 쓰레드가 작업을 처리할 수 있기 때문에 보다 효율적인 CPU 사용 가능!

 

예제1) 싱글쓰레드 프로세스로 다중작업을 처리(사용자에게 입력 + 숫자 카운트다운)

 

import javax.swing.JOptionPane;

public class Ex13_4 {

	public static void main(String[] args) {
		String input = JOptionPane.showInputDialog("아무값이나 입력하세요.");
		System.out.println("입력한신 값은 " + input + " 입니다.");
		
		for(int i=10;i>0;i--) {
			System.out.println(i);
			try {
				Thread.sleep(1000);  // 1초간 시간을 지연한다.
			} catch(Exception e) {}
		}
	}
}

 

더보기

sleep( )는 메서드 자체가 항상 exception을 throw하기 때문에 try-catch구문으로 예외처리를 해주었다!

sleep( )을 속도 조절을 위해서 사용! 

-> 사용자가 입력을 마치기 전까지는 화면에 숫자가 출력되지 않다가 사용자가 입력을 마치면 화면에 숫자가 출력됨

 

 

예제2) 예제1을 멀티쓰레드 프로세스로 작업을 처리

 

import javax.swing.JOptionPane;

public class Ex13_5 {
	public static void main(String[] args) {
		ThreadEx5_1 t1 = new ThreadEx5_1();  // 카운트다운 for문 실행하는 ThreadEx5_1 객체 생성
		t1.start();  // for문 실행
		
		String input = JOptionPane.showInputDialog("아무값이나 입력하세요");
		System.out.println("입력하신 값은 " + input + "입니다.");
	}
}
class ThreadEx5_1 extends Thread {
	public void run() {
		for(int i=10;i>0;i--) {
			System.out.println(i);
			try {
				Thread.sleep(1000);  // 1초씩 출력 쉼
			} catch (Exception e) {}
		}
	}
}

 

더보기

-> 입력하는 작업과 countdown 하는 작업이 분리되어 있어서 사용자가 입력을 하지 않아도 카운트다운이 출력된다.

<출력값>

10
9
8
7
입력하신 값은 123456입니다.
6
5
4
3
2
1