아메리카노가 그렇게 맛있답니다 여러분

일반적으로 한 프로그램은 한 프로세서입니다. 사람으로 비유하면 글을 쓸 때 한 사람이 글을 쓰는 것과 같습니다.

서점에 가봅시다. 서점에서 책을 한 권 집어보면 저자가 몇 명인가요? 한 명일 수도 있겠지만 많은 책들이 복수의 저자가 노력하여 책 한 권을 만들어냅니다. 프로그램도 필요에 따라 한 프로그램에서 여러 쓰레드를 이용하여 일을 해낼 수 있습니다.


사실 쓰레드는 우리가 하는 프로그래밍에 밀접하게 접해있을 수도 있습니다. 모든 클래스가 쓰레드를 사용하는 것은 아니지만 어떤 클래스는 쓰레드를 사용하여 만들어졌기 때문입니다. (참고:: StringBuffer와 StringBuilder의 차이)


쓰레드를 사용하는 클래스는 두 가지 방법으로 만들 수 있습니다.

첫째는 Thread 클래스를 상속받는 것입니다.

Thread클래스를 상속받으면 다른 클래스를 상속받을 수 없다는 단점이 있지만 Thread클래스가 가진 유용한 메소드들을 쓸 수 있다는 점에서 쓰레드 관리가 한결 쉬워집니다.


public class extThreadExample extends Thread { public int number; public extThreadExample(int number) { this.number = number; } public void run() { //main처럼 자동으로 실행되는 run()메소드 for(int i = 0 ; i < number; i++) { System.out.println(i); } } }


둘째는 Runnable이라는 인터페이스를 사용하는 것입니다.

Runnable을 사용하면 다른 클래스를 상속받을 수 있기 때문에 상속문제로부터 자유로워지지만 Thread클래스를 사용할 때처럼 쓰레드를 편하게 사용하기는 힘듭니다. 자기가 필요하면 이리저리 찾아서 써야하죠.


public class impRunnableExample implements Runnable {
	public int number;
	public impRunnableExample(int number) {
		this.number = number;
	}
	public void run() { //main처럼 자동으로 실행되는 run()메소드
		for(int i = 0; i < number; i++)
			System.out.println(i);
	}
}


쓰레드는 동시에 여러 작업을 할 수 있게 해줍니다. 다른 말로 한 작업을 여러 명이서 할 수 있다는 뜻인데, 이는 책 한 페이지를 작가 2~3명이 쓰는 것과 같습니다. 모든 작가가 다른 작가를 신경쓰지 않고 페이지 첫 줄부터 글을 써 나간다면 그 글은 몇 번이나 덧칠(?)되어 우리가 읽지 못하게 됩니다. 쓰레드도 마찬가지입니다. 기본적으로 쓰레드끼리는 다른 쓰레드가 무엇을 하는지 전혀 간섭하지 않습니다.

예를 들어, 1~5까지 출력하는 extThreadExample을 for문을 사용하여 5개 만들었을 경우, 순서대로 1~5를 다섯 번 찍어낼까요?


public class Execute {
	public static void main(String[] args) {
		extThreadExample[] ex = new extThreadExample[5];
		for(int i = 0; i < 5; i++) {
			ex[i] = new extThreadExample(5);
			ex[i].start();
		}
	}
}


첫 번째까지는 어떻게 찍어낼 수 있겠지만 두 번째부터는 찍지 못합니다. 그나마 예제에서 생성자 부분에 아무 출력문구가 없어서 첫 번째는 0~5가 대부분 출력되는 것일 뿐, 생성자 부분에 출력 문구가 있으면 첫 번째부터 원하는대로 출력되지 않습니다.

이럴 때 Thread클래스가 진가를 발합니다. Thread클래스는 getState()라는 메소드를 통해 쓰레드의 현재 상태를 알 수 있습니다.

getState()를 사용하여 상태를 계속 체크하면서 돌린다면 출력할 때 겹쳐서 출력되는 일이 없을 것입니다.


public class Execute {
	public static void main(String[] args) {
		extThreadExample[] ex = new extThreadExample[5];
		for(int i = 0; i < 5; i++) {
			ex[i] = new extThreadExample(5);
			ex[i].start();
			while(true)
				if(ex[i].getState() == Thread.State.TERMINATED)
					break;
		}
	}
}


Thread클래스를 상속한 경우 setPriority()를 사용하여 중요도를 구분할 수 있습니다. 중요도를 어떻게 나누느냐?

멀티태스킹이 사실은 여러 작업을 매우 빠르게 번갈아가면서 한다는 점에 초점을 두어야 합니다. chrome과 explorer를 띄우면 컴퓨터는 이 두 작업을 매우 빠르게 돌아가며 수행합니다. (이때 멀티코어는 배제합니다.)

Priority는 번갈아 작업하는 비율을 중요도로 따집니다. chrome이 더 중요한 작업이라면 크롬 2~3번 보고 explorer를 보고 다시 크롬 2~3번 보는.. 그런 방식의 중요도죠.

Priority()를 다르게 준 뒤 작업하면 이전 작업이 너무 먼저 진행되어서 끝나버리지 않는 한, 우선순위가 높은 작업이 먼저 출력하고 끝냅니다.