JAVA/STUDY

[JAVA] 멀티 스레드(1)

코맹 2024. 2. 15. 17:24

 

 

멀티 스레드의 개념

💡 프로세스와 스레드

📌 프로세스란?

  • 운영체제에서 실행 중인 하나의 애플리케이션을 프로세스라고 부른다.
  • 즉, 사용자가 작성한 프로그램이 운영체제에 의해 메모리 공간을 할당받아 실행 중인 것을 말한다.
  • 하나의 애플리케이션은 다중 프로세스를 만들기도 한다.
  • 이러한 프로세스는 프로그램에 사용되는 데이터와 메모리 등의 자원, 그리고 스레드로 구성된다.

📌 스레드란?

  • 프로세스 내에서 실제로 작업을 수행하는 주체를 뜻한다.
  • 모든 프로세스는 한 개 이상의 스레드가 존재하여 작업을 수행한다.
  • 두 개 이상의 스레드를 가지는 프로세스를 멀티스레드 프로세스라고 부른다.

📌  멀티테스킹이란?

  • 두 가지 이상의 작업을 동시에 처리하는 것을 의미한다.
  • 운영체제는 멀티 태스킹을 할 수 있도록 CPU 및 메모리 자원을 프로세스마다 적절히 할당해주고, 병렬로 실행시킨다.
  • 멀티 태스킹은 꼭 멀티 프로세스를 의미하지는 않는다.

📌 멀티 프로세스 VS 멀티 스레드

  • 멀티 프로세스 : 여러 개의 cpu를 사용하여 여러 프로세스를 동시에 수행하는 것
    • 각 프로세스가 독립적인 메모리를 가지고 별도로 실행된다.
    • 하나의 프로세스에서 오류가 발생해도 다른 프로세스에 영향을 미치지 않는다.
      (1개의 프로세스가 죽어도 다른 프로세스들은 계속 실행된다.)
  • 멀티 스레드 : 하나의 프로세스 내에서 둘 이상의 스레드가 동시에 작업을 수행하는 것
    • 각 스레드가 자신이 속한 프로세스의 메모리를 공유한다.
    • 시스템 자원 낭비가 적다.
    • 하나의 스레드에 문제가 생기면, 전체 프로세스가 영향을 받는다.

 

메인 스레드

더보기

모든 자바 프로그램은 메인 스레드가 main() 메소드를 실행하면서 시작된다.

  • 메인 스레드는 main() 메소드의 첫 코드부터 순차적으로 실행하고, main() 메소드의 마지막 코드를 실행하거나  return문을 만나면 실행이 종료된다.
  • 메인 스레드는 필요에 따라 추가 작업 스레드들을 만들어서 병렬로 코드를 실행할 수 있다.
  • 즉, 멀티 스레드를 생성해서 멀티 태스킹을 수행한다.

 

  • 싱글 스레드
    • 메인 스레드가 종료되면 프로세스도 종료된다.
    • 싱글 스레드가 메인 스레드이다.
  • 멀티 스레드
    • 실행 중인 스레드가 하나라도 있다면 프로세스는 종료되지 않는다.
    • 메인 스레드가 작업 스레드보다 먼저 종료되더라도 작업스레드가 계속 실행 중이라면 프로세스는 종료되지 않는다.

 

작업 스레드 생성과 실행

멀티 스레드로 실행하는 애플리케이션을 개발하려면 먼저 몇 개의 작업을 병렬로 실행할지 결정하고 각 작업별로 스레드를 생성해야 한다.

 

어떤 자바 애플리케이션이건 메인 스레드는 반드시 존재하기 때문에 메인 작업 이외에 추가적인 병렬 작업의 수만큼 스레드를 생성하면 된다.

 

public class ThreadOne {
	public static void main(String[] args) {
		Thread tc = Thread.currentThread();		// 객체 생성없이 Class이름인 Thread로 접근하고 있음. 즉 static 멤버라는 것을 알 수 있음
		System.out.println(tc.getName());
		
	}

}

 

☝️  main이 출력되는 것을 볼 수 있다.

 

 

자바에서 스레드를 생성하는 방법은 2가지가 있다.

  • java.lang.Thread 클래스를 직접 객체화해서 생성하는 방법
  • Thread 를 상속해서 하위 클래스를 만들어 생성하는 방법

 

1. Thread 클래스로 직접 생성

java.lang 패키지에 있는 Thread 클래스로부터 작업 스레드 객체를 직접 생성하려면 다음과 같이  Runnable 구현 객체를 매개값으로 갖는 생성자를 호출하면 된다.

더보기

Thread thread = new Thread(Runnable target);

 

Runnable이 무엇인가

스레드가 작업을 실행할 때 사용하는 인터페이스이다.

Runnable에는 run() 메소드가 정의되어 있는데, 구현 클래스는 run()을 재정의해서 스레드가 실행할 코드를 가지고 있어야 한다.

class Task implements Runnable  {
	@Override
    public void run() {
    	// 스레드가 실행할 코드
    }
}

 

 

✔️  Thread 생성

1) 기본 형태

Runnable task = new Task();
Thread thread = new Thread(task);

☝️ Runnable 구현 객체를 생성한 후 Thread 생성자 매개값으로 Runnable 객체에 전달해주어야 한다.

 

2) 익명 객체 사용

Thread thread = new Thread(new Runnable() {
	@Override
    public void run() {
    	// 스레드가 실행할 코드
    }
})

☝️ 이 방법은 명시적인 Runnable 구현 클래스를 작성하지 않고, Thread 생성자를 호출할 때  Runnable 익명 구현 객체를 매개값으로 사용할 수 있다.

 

 

✔️  Thread 실행

작업 스레드 객체가 생성되었다고 해서 바로 작업 스레드가 실행되지는 않는다. 작업 스레드를 실행하려면 스레드 객체의 start() 메소드를 호출해야 한다.

더보기

thread.start();

start() 메소드가 호출되면 작업 스레드는 매개값으로 받은 Runnable의 run() 메소드를 실행하면서 자신의 작업을 처리한다.

 

 

 

2. Thread 자식 클래스로 생성

작업 스레드가 실행할 작업을 Runnable로 만들지 않고, Thread 하위 클래스로 작업 스레드를 정의하면서 작업 내용을 포함시킬 수도 있다.

 

 

✔️ 작업 Thread  클래스 정의 방법

1) 기본 형태

Thread 클래스 상속한 후 run 메소드를 재정의(overriding)해서 스레드가 실행할 코드를 작성한다.

작업 스레드 클래스로부터 작업 스레드 객체를 생성하는 방법은 일반적인 객체를 생성하는 방법과 동일하다.

public class WorkerThread extends Thread() {
	@Override
    public void run() {
    	// 스레드가 실행할 코드
    }
}

// 스레드 객체 생성
Thread thread = new WorkerThread();

 

 

2) 익명 객체 이용

코드 절약을 위해 Thread 익명 객체로 작업 스레드 객체를 생성할 수도 있다.

Thread thread = new Thread() {
	@Override
    public void run() {
    	// 스레드가 실행할 코드
    }
};

thread.start();

 

 

 

스레드 이름

스레드는 자신의 이름을 가지고 있다. 주로 디버깅할 때 어떤 스레드가 작업을 하는지 조사할 목적으로 사용된다.

메인 스레드는 'main', 작업 스레드는 ' Thread -n' 이라는 이름을 가진다. 작업 스레드의 이름을 Thread-n 대신 다른 이름으로 설정하고 싶다면 Thread 클래스의 setName() 메소드를 사용하면 된다.

 

✔️ 스레드 이름 설정

thread.setName("스레드 이름");

 

 

✔️ 스레드 이름 출력

Thread thread = Thread.currentThread();
System.out.println(thread.getName());

 

  • 예제
package ch14.sec04;

public class ThreadNameExample {
	public static void main(String[] args) {
		Thread mainThread = Thread.currentThread();
		
		System.out.println(mainThread.getName() + "실행");
		
		for (int i = 0; i < 3; i++) {
			Thread threadA = new Thread() {
				@Override
				public void run() {
					System.out.println(getName() + " 실행");
					
				}
				
			};
			threadA.start();
			
		}
		
		Thread chatThread = new Thread() {
			@Override
			public void run() {
				System.out.println(getName() + "실행");
				
			}
			
		};
		
		chatThread.setName("chat-thread");
		chatThread.start();
		
	}

}

 

 

스레드 상태

  • 스레드 객체를 생성(NEW)하고, start() 메소드를 호출하면 곧바로 스레드가 실행되는 것이 아니라 실행 대기 상태(RUNNABLE)가 된다. 
  • 실행 대기하는 스레드는 CPU 스케쥴링에 따라 CPU를 점유하고 run() 메소드를 실행한다. 이때를 실행(RUNNING) 상태라고 한다.
  • 실행 상태에서 run() 메소드가 종료되면 더 이상 실행할 코드가 없기 때문에 스레드 종료 상태(TERMINATED)로 바뀐다.

 

 

실행상태에서 일시정시 상태로 가기도 하는데, 일시 정지 상태는 스레드가 실행할 수 없는 상태를 말한다.

다시 실행상태로 가기 위해서는  실행 대기 상태로 가야 한다.

 

 

'JAVA > STUDY' 카테고리의 다른 글

[Java] Enum 열거형 타입  (0) 2024.08.09
[JAVA] 배열 (Array)  (2) 2024.02.14
[JAVA] 조건문과 반복문(if, switch, for, while문)  (3) 2024.02.12
[JAVA] 자바 변수, 선언, 초기화  (2) 2024.02.12