프로세스와 스레드

>>

더보기

프로세스 Process

- 운영체제로부터 자원을 할당받은 작업의 단위로, 실행중인 하나의 프로그램을 의미한다.

- 리소스(resource)와 스레드(thread)로 구성된다.

- Code, Data, Heap, Stack영역으로 이루어지며, 각각의 메모리 공간을 차지한다.

- 동시에 두 개 이상의 프로그램을 특정 기법으로 동시에 실행시키는 기능을 멀티 태스킹(multitasking) 이라 한다. 특정 기법에는 대표적으로 시분할(Time-Shared)기법이 있다.

 

스레드 Thread

- 프로세스 내에서 실행되는 흐름의 단위이다. 즉, 프로세스가 할당 받은 자원을 이용하는 실행 단위(흐름)이다. 

- 스레드는 프로세스 내에 존재하며, 모든 프로세스는 적어도 하나이상의 스레드를 가지고 있다.

- 프로세스는 자신만의 메모리 공간과 자원을 할당받아 사용하지만, 스레드는 다른 스레드와 메모리와 자원을 공유한다.

Code, Data, Heap 영역은 공유하고 별도의 Stack영역만 가지고 있다.

- 둘 이상의 스레드를 가진 프로세스를 멀티 스레드 프로세스(multi-thread process)라 한다.

 

멀티 스레드 

장점

- 시스템의 자원소모가 줄어든다.

- CPU의 사용률을 향상시킨다.

- 프로그램의 응답 시간이 단축된다.

 

단점

- 자원 공유를 위해 전역변수를 이용하므로 동기화 관련된 문제가 발생할 수 있다.

- 잘못된 변수를 사용하거나 미묘한 시간차로 인해 프로그램에 오류가 발생할 수도 있다.

- 디버깅이 어렵다.

스레드 구현 및 실행

>>

더보기

자바 메인 스레드

- 자바는 프로그램(process)이 시작되면 기본적으로 main() 메소드를 진입점(Entry Point)으로 하는 메인 스레드(Main Thread)가 생성되며, 사용자가 정의한 스레드를 생성함으로써 멀티 스레드를 구현할 수 있다.

- main()메소드는 프로그램의 진입점이지 종료점이 아니므로, 멀티 스레드 환경에서는 모든 스레드가 종료되야 프로세스가 종료된다.

 

java.lang.Thread 클래스

- 스레드 생성 및 시작, 관리를 위한 클래스이다.

- Thread 클래스를 상속 받은 하위 클래스에서 run() 메소드를 재정의하여 스레드를 구현한다.

 

java.lang.Runnable 인터페이스

- 스레드에서 실행할 코드를 가지는 run() 메소드가 선언되어 있다.

- 자바는 단일 상속만 구현 가능하므로 스레드를 구현할 클래스가 다른 클래스를 상속 받은 경우 Runnable 인터페이스를 구현한다.

- Runnable 인터페이스를 implements 한 클래스는 run() 메소드를 재정의하여 스레드를 구현한다.

 

스레드 시작

- 스레드를 실행하기 위해서는 Thread 클래스의 start() 메소드를 호출하면 스레드를 시작한다. start() 메소드에 의해 스레드가 시작되면, 자바 가상 머신은 이 스레드의 run() 메소드를 호출한다.

- 스레드 시작 방법

 1) Thread 클래스를 상속받는 하위 클래스 만든 경우 : 해당 클래스의 객체를 생성한 후 Thread 클래스의 start() 메소드를 호출한다.

 2) Runnable 인터페이스를 구현하여 클래스를 만든 경우 : Thread(Runnable target) 생성자에 Runnable 인터페이스 구현 클래스 객체를 인수로 넘겨 Thread 클래스의 객체를 생성하여 Thread 클래스의 start() 메소드를 호출한다.

 

스레드 종료

- 스레드의 종료는 run() 메소드가 종료되는 시점이다.

- Thread 클래스의 stop() 메소드를 이용하여 강제로 스레드를 종료할 수 있지만 사용을 권장하지 않는다.

스레드 예제

Ex001_Thread : Thread 클래스를 이용한 스레드 구현 >>

더보기

 

package threadEx;

public class Ex001_Thread {

	public static void main(String[] args) {
		MyThread1 t = new MyThread1();

		t.start(); // 스레드 시작
		// t.run(); // 유저가 부르면 Tread가 아님.
		
		try {
			for (int i = 1; i <= 10; i++) {
				System.out.println("main -> " + i);
				Thread.sleep(100);
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		System.out.println("main 종료 !!!");
		// main은 프로그램의 시작점이지만 종료점은 아니다.
		// main이 종료되어도 프로그램은 종료되지 않을 수 있다.
		// 프로그램의 종료 시점은 모든 독립스레드가 종료되는 시점이다.
	}
}

// 스레드 구현방법 - 1
//	1) Thread 클래스를 상속 받아 run() 메소드를 override한다.
//	2) Thread 클래스를 상속 받은 클래스의 객체를 생성하여 start() 메소드를 호출한다.
class MyThread1 extends Thread {

	@Override
	public void run() {
		int n = 0;

		try {
			while (n < 20) {
				n++;
				System.out.println(getName() + " -> " + n);

				sleep(500); // 지정 시간(단위:ms)동안 스레드 실행이 일시 중지됨.
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

	}
}

스레드클래스를 상속받아 run() 메소드를 override 해서 클래스의 객체를 생성해서 start()메소드로 멀티 스레드를 구현했다. main 에서도 이미 Thread가 (main() 메소드를 진입점으로 하는 메인 스레드가 존재) 있기 때문에 둘을 비교해보았다.

main()이 종료되어도 프로그램 종료는 모든 독립 스레드가 종료된 후에 일어난다.

Ex002_Runnable : Runnable 인터페이스를 이용한 스레드 구현 >>

더보기
package threadEx;

public class Ex002_Runnable {
	public static void main(String[] args) {
		MyThread2 th = new MyThread2();
		Thread t = new Thread(th);
		t.start();
		
		try {
			for (int i = 1; i <= 10; i++) {
				System.out.println("main -> " + i);
				Thread.sleep(100);
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		System.out.println("main 종료 !!!");
	}
}

// 스레드 구현방법 - 2
//	1) Runnable 인터페이스를 구현하는 클래스를 만들어 run() 메소드를 override 한다.
//	2) Runnable 인터페이스 구현 클래스 객체를 생성한다.
//	3) Thread 클래스를 객체를 생성하며, Thread 객체를 생성할 때 생성자의 인자에 2)번에서 생성한 객체를 넘긴다.
//	4) 
class MyThread2 implements Runnable {

	@Override
	public void run() {
		int n = 0;

		try {
			while (n < 20) {
				n++;
				System.out.println(Thread.currentThread().getName() + " -> " + n);
				Thread.sleep(500);
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}

}

Runnable 인터페이스를 구현하는 클래스를 만들어 run() 메소드를 override한 후 Runnable 인터페이스 구현 클래스 객체를 생성한다. Thread 클래스 객체를 생성하여 생성자의 인자에 Runnable 구현 클래스 객체를 넘겨준다.

Ex003_Runnable : 익명 클래스를 이용한 스레드 구현 >> 

더보기
package threadEx;

public class Ex003_Runnable {

	public static void main(String[] args) {
		// 스레드 구현방법 - 3 : 익명 클래스를 이용한 스레드 구현
		Thread t = new Thread(new Runnable() {

			@Override
			public void run() {
				try {
					for (int n = 1; n <= 20; n++) {
						System.out.println("스레드 -> " + n);
						Thread.sleep(500);
					}
				} catch (InterruptedException e) {
					e.printStackTrace();
				}

			}
		});

		t.start();

		try {
			for (int i = 1; i <= 10; i++) {
				System.out.println("메인 -> " + i);
				Thread.sleep(100);
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		System.out.println("메인 종료 !!!");
		
	}

}

익명클래스는 전에 수업시간에 한 번 보고 나서 너무 오랫만에 보는 클래스라 너무 낯설었다.

Ex004_Runnable : 람다를 이용한 스레드 구현 >>

더보기
package threadEx;

public class Ex004_Runnable {

	public static void main(String[] args) {
		// 스레드 구현 방법 - 4 : 람다를 이용한 스레드 구현
		Thread t = new Thread( () -> {
			try {
				for (int n = 1; n <= 20; n++) {
					System.out.println("스레드 -> " + n);
					Thread.sleep(500);
				}
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		});

		t.start();

		try {
			for (int i = 1; i <= 10; i++) {
				System.out.println("메인 -> " + i);
				Thread.sleep(100);
			}
		} catch (InterruptedException e) {
			e.printStackTrace();
		}

		System.out.println("메인 종료 !!!");

	}

}

람다는 아직 배우지 않았으므로 그냥 이렇게 구현할 수 있구나~ 정도만 알면 된다고 하셨다.

 

+ Recent posts