Thread

박주현·2022년 11월 8일
0

국비 공부

목록 보기
26/44

프로세스와 멀티태스킹의 개념

프로세스(Process)는 실행 중인 프로그램으로, 디스크에 있는 프로그램이 메모리에 적재되어 운영체제의 제어를 받는 상태를 의미한다. 프로세스는 자신만의 자원을 가진다. 따라서 여러 프로세스를 동시에 실행하더라도 자신만의 메모리를 사용하기 때문에 서로 독립적이다.

사용자는 문서 작업을 하면서 동시에 미디어 재생기로 음악을 감상할 수 있다. 이런 두 가지 이상의 작업을 동시에 처리하는 것을 멀티태스킹(multi-tasking)이라고 한다. 멀티 코어 CPU라면 실제로 다수의 작업을 동시에 병렬(Parallel)처리 하지만, 싱글 코어 CPU라면 운영체제가 CPU 시간을 분할해서 교대로 각 작업에 할당해 다수의 작업을 병행(concurrent) 처리한다.

스레드의 개념

스레드(thread)는 사전적인 의미로 한 가닥의 실이다. 작업을 실행하는 코드의 흐름이 바느질할 때의 실처럼 이어진 것과 같기 때문이다. 스레드느 ㄴ하나의 실행 흐름으로 프로세스 내부에 존재한다. 하나의 프로세스는 하나 이상의 실행 흐름을 포함하기 때문에 프로세스는 적어도 하나의 스레드를 가진다. 스레드는 경량 프로세스(lightweight process)라고도 한다. 이는 스레드가 프로세스에 비해 실행 환경에 필요한 자원이 매우 적기 때문이다. 스레드는 메모리와 파일 등 모든 자원을 프로세스와 공유한다.

자바 어플리케이션의 실행 환경인 JVM은 하나의 프로세스로 실행된다. 자바 어플리케이션을 실행하려면 JVM이 필요하며, 하나의 JVM은 하나의 어플리케이션만 실행할 수 있다.

스레드 생성 방법

class MyRunnable implements Runnable {	// Runnable을 구현하여 사용하는 방법
	@Override
	public void run() {
		for (int i = 0; i < 5; i++) {
			System.out.println("잘가. ");
			try {
				Thread.sleep(600);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}

}

public class Thread1Demo {
	public static void main(String[] args) throws InterruptedException {
    	MyRunnable myRunnable = new MyRunnable();	// 클래스 선언 후 사용
		myRunnable.run();
        
		new Thread(new Runnable() {	// 익명 메서드로 사용.
			@Override
			public void run() {
				for (int i = 0; i < 5; i++) {
					System.out.println("안녕. ");
					try {
						Thread.sleep(500);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}).start();

		new Thread(new Runnable() {	// 익명 메서드로 사용.
			@Override
			public void run() {
				for (int i = 0; i < 5; i++) {
					System.out.println("잘가. ");
					try {
						Thread.sleep(600);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		}).start();

		Runnable task = () -> {	// 람다식으로 사용
			for (int i = 0; i < 5; i++) {
				System.out.println("안녕. ");
				try {
					Thread.sleep(500);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		};

		Runnable task2 = () -> {	// 람다식으로 사용
			for (int i = 0; i < 5; i++) {
				System.out.println("잘가. ");
				try {
					Thread.sleep(600);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		};

		new Thread(task).start();
		Thread.sleep(500);
		new Thread(task2).start();

	}

}

스레드 생성과 실행

스레드 풀을 이용한 스레드 실행

  • 스레드의 개수가 많아지면 그에 따른 스레드 객체 생성과 스케줄링 등으로 CPU와 메모리에 많은 부하가 발생 -> 동시에 실행하는 스레드 개수를 제한할 필요
  • 스레드 풀은 제한된 개수의 스레드를 JVM에 관리하도록 맡기는 방식
  • JDK5부터 ExecutorService 인터페이스와 Executors 클래스를 포함하는 java.util.concurrent 패키지를 이용해 지원
  • Executor를 사용하는 대표적인 코드
Runnable task = () -> {

};
Executor exec = Executors.newChachedThreadPool();
exec.execute(task);
public class ThreadPoolDemo {
	public static void main(String[] args) {
		Runnable task = () -> {
			for (int i = 0; i < 5; i++) {
				System.out.print("잘가. ");
				try {
					Thread.sleep(500);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		};

		ExecutorService exec = Executors.newCachedThreadPool();
		// ExecutorService exec = Executors.newCachedThreadPool(4);
		exec.execute(task);
//		exec.submit(task);

		for (int i = 0; i < 5; i++) {
			System.out.println("안녕. ");
		}
		try {
			Thread.sleep(500);
		} catch (InterruptedException e) {
			exec.shutdown();
		}

	}

}

출력
안녕. 
안녕. 
안녕. 
안녕. 
안녕. 
잘가. 잘가. 잘가. 잘가. 잘가. 

0개의 댓글