:: 멀티태스킹 - 하나의 CPU가 여러 개의 프로세스를 교대로 수행하는 것입니다.
윈도우에서는 웹 서핑을 하면서 영화를 보기도 하고 메신저를 하기도 합니다. 이렇게 컴퓨터 한 대에서 여러가지 작업을 할 수 있는 것을 멀티태스킹이라고 합니다. 이러한 작업이 가능하게 하기 위해서 CPU는 시간을 분할하여 각 프로그램에 제어권을 한 번씩 나누어 주면서 CPU를 적절하게 사용하는 것입니다. 멀티태스킹은 운영체제에서 제공해주는 기능이므로 우리가 프로그래밍할 수 있는 부분이 아닙니다.
:: 멀티스레딩 - 하나의 CPU가 여러 개의 스레드를 교대로 수행하는 것입니다.
자바 프로그램은 기본적으로 main()메서드가 수행되면서 하나의 스레드가 동작하게 됩니다. 하지만 자바에서는 main()메서드에 의한 스레드 이외의 다른 스레드도 동작 시킬수 있도록 Thread 클래스를 제공합니다. Thread 클래스를 사용하면 하나의 프로그램에서 스레드를 여러개 둘 수 있는 것을 멀티스레딩이라고 합니다.
멀티스레딩은 하나의 프로세스를 여러 개의 작은 작업 단위로 나누어서 실행하는 것을 의미합니다. P2P방식의 파일다운 받는 프로그램을 이용하여 파일을 전송하는 프로그램을 단일 스레드로 구현하여 한 개의 파일을 다 전송받아야 다른 작업을 할 수 있게 됩니다. 다운 받을 파일의 용량이 클 경우, 이 파일을 전송 받는 동안(오랜 시간동안) 아무런 작업도 하지 못하게 됩니다.
하지만, 우리가 현재 사용중인 FTP프로그램들은 파일 전송 받는 작업을 멀티스레드로 구현해 놓았기 때문에 용량이 큰 파일을 다운받는 중이라도 또 다른 파일을 전송받거나 다른 작업을 할 수 있도록 합니다.
다운 받을 파일이 여러 개 일 경우 한꺼번에 여러 개의 파일을 다운 받을 수 있도록 한꺼번에 다운로드 창이 열리면서 다운로드가 진행됩니다.
하나의 프로그램에서 다운하는 작업을 스레드로 본다면 여러 개의 스레드가 동시에 CPU에 의해서 수행되고 있습니다. 이렇게 하나의 프로그램에서 여러 개의 작업이 동시에 수행되는 것을 멀티스레드라고 하며 이 기능은 프로그램을 개발하는 프로그래머에 의해서 구현됩니다.
정리하면 하나의 프로세스가 여러가지 작업을 처리해야 할 때 CPU가 내부적으로 이러한 작업을 독립된 모듈로 나우어 놓는데 이러한 세부 실행 단위를 스레드라고 합니다.
멀티스레드로 멀티태스킹과 마찬가지로 나누어 놓은 작업 단위인 스레드를 수행하기 위해서 CPU를 시분할하여 교대로 수행하는 것을 의미하며, CPU 내부에서는 한 순간에 한 가지 작업만 하지만 멀티스레드로 구현된 응용프로그램을 사용하는 사용자는 동시에 여러작업이 일어나는 것으로 착각하게 됩니다.
하나의 스레드만 동작하는 애플리케이션에서는 오래 걸리는 작업이 먼저 수행중이라면 그 작업이 끝나기 전까지 다른 작업을 못하는 아쉬움이 있습니다. 이런 아쉬움을 멀티스레드를 이용하면 해결됩니다.
자바에서는 멀티스레드가 지원됩니다. 자바에서 사용할 수 있는 스레드는 두 가지 형태입니다.
1. Thread 클래스를 상속받는 방법
2. Runnable 인터페이스를 구현하는 방법
Thread 클래스를 상속받는 방법이 구현하기 쉽기는 하지만, 이미 다른 클래스의 상속을 받고 있는 클래스는 자바에서 다중 상속이 불가능하므로 스레드 클래스의 상속을 받을 수 없으므로 Runnable 인터페이스를 구현해야 합니다.
- Thread 클래스 -
<< 예제 01>>
// 멀티스레드를 지원하는 클래스를 만들려면 java.lang.Thread 클래스의 상속받아야 함
class ThreadExam extends Thread {
ThreadExam(String name) { // 생성자에 스레드 이름이 전달인자로 넘어 옴
// ThreadExam의 상위 클래스인 Thread의 생성자(super)를 호출
super(name); // 전달인자로 준 값이 스레드의 이름이 됨
}
// 스레드 객체가 수행해야 하는 작업을 run() 메서드를 오버라이딩하여 이 내부에 기술
public void run() {
for (int num = 1; num <= 5; num++) {
for (int k = 1; k < 100000000; k++); // 시간을 필요로 하는 작업을 위한 설정
// 스레드의 이름을 얻어 출력함
System.out.println(getName() + " : " + num);
}
}
}
class ThreadTest01 {
public static void main(String[] args) {
// 스레드 클래스를 인스턴스화하여 독립된 스레드를 생성
ThreadExam t1 = new ThreadExam("첫 번째 스레드");
ThreadExam t2 = new ThreadExam("두 번째 스레드");
// start() 메서드를 호출하면 스레드 객체의 run() 메서드가 돌면서 스레드가 실행
t1.start();
t2.start();
}
}
<< 예제 02 >>
스레드를 사용하지 않고 작성한 한 개의 스레드만 존재하는 자바 프로그램을 << 예제 01 >> 과 유사하게 동작하도록 작성해서 두 프로그램을 비교해 보도록 하겠습니다.
class ThreadExam {
String name; // 수행되는 스레드를 구분하기 위해서 스레드의 이름을 지정
ThreadExam(String name) { // 스레드를 생성할 때 스레드 이름을 결정함
this.name = name;
}
public void start() { // 스레드가 아닌데 스레드처럼 동작하도록 하기 위해서
run(); // start() 메서드를 정의하고 여기서 run() 메서드를 호출함
}
// 스레드 객체가 수행해야 하는 작업을 run() 메서드를 오버라이딩하여 이 내부에 기술
public void run() {
// 1부터 5까지를 출력하도록 함
for (int num = 1; num <= 5; num++) {
// 이때 시간이 어느정도 걸려야 스레드가 제대로 동작하는지를 살펴볼 수 있기 때문에
for (int k = 1; k < 100000000; k++); // 반복문을 이용하여 시간을 지쳐지도록 함
System.out.println(name + " : " + num);
}
}
}
class ThreadTest02 {
public static void main(String[] args) {
ThreadExam t1 = new ThreadExam("첫 번째 스레드");
ThreadExam t2 = new ThreadExam("두 번째 스레드");
t1.start();
t2.start();
}
}
- Runnable 인터페이스 -
스레드를 생성하기 위한 다른 방법은 Runnable 인터페이스를 구현하는 클래스를 선언하는 것입니다.
다음과 같이 Runnable 인터페이스를 구현하는 클래스의 인스턴스를 생성한 후, 스레드를 생성할 때 매개변수로 넘겨야 합니다.
RunnableExam r1 = new RunnableExam();
Thread t1 = new Thread(r1);
t1.start();
Thread 클래스의 인스턴스를 생성하면서 Runnable 인터페이스를 구현하는 클래스의 인스턴스를 매개변수로 전달해 줌으로써, Thread 클래스의 서브클래스를 생성하지 않고서도 스레드를 구현할 수 있습니다.
<< 예제 03 >>
// Runnable 인터페이스를 구현하는 클래스를 선언
class RunnableExam implements Runnable {
public void run() {
for (int num = 1; num <= 5; num++) {
// 시간을 필요로 하는 작업
for (int k = 1; k < 100000000; k++);
// 어떤 스레드가 수행중인지 확인하기 위해서 스레드의 이름을 얻어와서 숫자와 함께 출력해준다.
System.out.println(Thread.currentThread().getName() + " : " + num);
}
}
}
class ThreadTest03 {
public static void main(String[] args) {
// Runnable 인터페이스를 구현하는 클래스의 인스턴스를 생성
RunnableExam r1 = new RunnableExam();
RunnableExam r2 = new RunnableExam();
// 스레드를 생성할 때 Runnable 인터페이스를 구현하는 클래스의 인스턴스를 매개변수로 넘겨줌
Thread t1 = new Thread(r1, "첫 번째 스레드");
Thread t2 = new Thread(r2, "두 번째 스레드");
t1.start();
t2.start();
}
}
'IT이론 > os' 카테고리의 다른 글
교착상태 (deadlock) (0) | 2014.01.24 |
---|---|
임계구역 문제 (0) | 2014.01.24 |
Atomic Operation 이란? (1) | 2014.01.24 |
대칭형 다중 처리 (SMP) (0) | 2014.01.24 |
유저모드와 커널모드 (0) | 2014.01.24 |