프로세스 vs 쓰레드
- 프로세스 : 운영체제로부터 자원을 할당받는 작업의 단위
- 쓰레드 :프로세스가 할당받은 자원을 이용하는 실행의 단위
ex) 카카오톡, 브라우저, JAVA프로그램
OS가 프로그램 실행을 위한 프로세스(resource)를 할당해줄때 프로세스안에 프로그램 Code와 Data 그리고 메모리 영역(Stack, Heap)을 함께 할당해줌
Code : Java main 메소드와 같은 코드
Data : 프로그램이 실행중 저장 할 수 있는 저장공간
Memory (메모리 영역)
프로세스 안에는 여러 쓰레드(일꾼)들이 있고, 쓰레드들은 실행을 위한 프로세스 내 주소공간이나 메모리공간(Heap)을 공유 받음
추가로, 쓰레드(일꾼)들은 각각 명령처리를 위한 자신만의 메모리공간(Stack)도 할당 받음
일반 쓰레드와 동일하며 JVM 프로세스 안에서 실행되는 쓰레드
Java 프로그램을 실행하면 앞서 배운 JVM 프로세스 위에서 실행됨
Java 프로그램 쓰레드는 Java Main 쓰레드부터 실행되며 JVM에 의해 실행됨
Java는 메인 쓰레드가
main()
메서드를 실행시키면서 시작
- 메인 쓰레드는 필요에 따라서 작업 쓸레드들을 생성해서 병렬로 코드를 실행 시킬 수 있음
- 즉, Java는 멀티 쓰레드를 지원
프로세스 안에서 하나의 쓰레드만 실행되는 것
Java 프로그램의 경우 main()
메서드만 실행시키면 싱글 쓰레드
Java 프로그램 main()
메서드의 쓰레드를 메인 쓰레드
JVM 의 메인 쓰레드가 종료되면, JVM 도 같이 종료
프로세스 안에서 여러개의 쓰레드가 실행되는 것
하나의 프로세스는 여러 개의 실행 단위(쓰레드)를 가질 수 있으며 이 쓰레드들은 프로세스의 자원을 공유함
Java 프로그램은 메인 쓰레드 외에 다른 작업 쓰레드들을 생성하여 여러 개의 실행 흐름을 만들 수 있음
동기화 문제(Synchronization Problem)가 발생할 수 있음
교착 상태(Deadlock(데드락))이 발생할 수 있음
병목현상(Bottleneck)이 발생할 수 있음
public class TestThread extends Thread{ // Thread 상속
@Override
public void run() {
// 실제 우리가 쓰레드에서 수행할 작업
for (int i = 0; i < 100; i++) {
System.out.print("*");
}
}
public class Main {
public static void main(String[] args) {
TestThread thread = new TestThread(); // Thread 생성
thread.start(); // Thread 실행
Thread 클래스를 상속받아 쓰레드 구현
run()
을 오버라이딩해서 수행할 작업 작성Thread 객체 생성후 start()
로 실행
public class TestRunnable implements Runnable { // Runnable 구현
@Override
public void run() {
// Thread에서 수행할 작업 정의!
for (int i = 0; i < 100; i++) {
System.out.print("$");
}
}
}
public class Main {
public static void main(String[] args) {
Runnable run = new TestRunnable(); // Runnable 생성
Thread thread = new Thread(run); // Thread 생성
thread.start(); // Thread 실행
Runnable 인터페이스를 사용하여 쓰레드 구현
run()
을 오버라이딩해서 수행할 작업 작성Runnable 구현 객체를 인자로 넣어 Thread 객체 생성 후 start()
로 실행
왜 Runnable을 사용하여 쓰레드를 구현할까?
- Thread는 클래스이므로 다중 상속되지 않아 확장성이 매우 떨어짐
- 반대로 Runnable은 인터페이스이기 때문에 다른 필요한 클래스를 상속받을 수 있어 확정성에 매우 유리!
public class Main {
public static void main(String[] args) {
Runnable task = () -> {
int sum = 0;
for (int i = 0; i < 50; i++) {
sum += i;
System.out.println(sum);
}
System.out.println(Thread.currentThread().getName() + " 최종 합 : " + sum);
};
Thread thread1 = new Thread(task);
thread1.setName("thread1");
Thread thread2 = new Thread(task);
thread2.setName("thread2");
thread1.start();
thread2.start();
}
}
run()
메서드에 작성했던 쓰레드가 수행할 작업을 실행 블록 { } 안에 작성
setName()
메서드 : 쓰레드에 이름을 부여
Thread.currentThread().getName()
: 현재 실행 중인 쓰레드의 이름을 반환