목표
자바의 멀티쓰레드 프로그래밍에 대해 학습하세요.
학습내용
Thread 클래스와 Runnable 인터페이스
쓰레드의 상태
쓰레드의 우선순위
Main 쓰레드
동기화
데드락
Thread 클래스와 Runnable 인터페이스
쓰레드(Thread)
쓰레드(thread)란 프로세스(process) 내에서 실제로 작업을 수행하는 주체를 의미한다.
모든 프로세스에는 한 개 이상의 스레드가 존재하여 작업을 수행한다.
또한, 두 개 이상의 스레드를 가지는 프로세스를 멀티스레드 프로세스(multi-threaded process)라고 한다.
프로세스(Process)
프로세스(process)란 단순히 실행 중인 프로그램(program)이라고 할 수 있다.
즉, 사용자가 작성한 프로그램이 운영체제에 의해 메모리 공간을 할당받아 실행 중인 것을 말한다.
이러한 프로세스는 프로그램에 사용되는 데이터와 메모리 등의 자원 그리고 쓰레드로 구성한다.
자바에서 쓰레드를 생성하는 방법은 두가지가 있다.
- Runnable 인터페이스를 구현
- Thread 클래스를 상속
Runnable 인터페이스는 몸체가 없는 메소드인 run() 메소드를 단 하나만 가지는 인터페이스이다.
package livestudy.week.ten;
import org.junit.jupiter.api.Test;
//thread 클래스를 상속 받아 생성
public class PracticeThread extends Thread{
public void run() {
for(int i=0;i<10;i++) {
System.out.println(getName());
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("class Thread fin.");
}
@Test
public void executeTest() {
PracticeThread thread1 = new PracticeThread();
Thread thread2 = new Thread(new PracticeThreadRunnable());
thread1.start();
thread2.start();
}
}
//runnable 인터페이스를 구현하여 생성
class PracticeThreadRunnable implements Runnable {
@Override
public void run() {
for(int i=0;i<10;i++) {
System.out.println(Thread.currentThread().getName());
try {
Thread.sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
System.out.println("interface Thread fin.");
}
}
쓰레드 상태
쓰레드 우선순위
각 쓰레드는 우선순위에 관한 자신만의 필드를 가지고 있다. 이러한 우선순위에 따라 특정 쓰레드가 더 많은 시간동안 작업을 할 수 있도록 설정할 수 있다.
필드 | 설명 |
static int MAX_PRIORITY | 쓰레드가 가질 수 있는 최대 우선순위 명시 |
static int MIN_PRIORITY | 쓰레드가 가질 수 있는 최소 우선순위 명시 |
static int NORM_PRIORITY | 쓰레드가 생성될 때 가지는 기본 우선순위 명시 |
getPriority()와 setPriority()메소드를 통해 쓰레드의 우선순위를 반환하거나 변경할 수 있다.
Main 쓰레드
자바에서 프로그램이 실행되면 하나의 쓰레드가 생성되고 해당 쓰레드에서 프로그램이 실행된다. 이 쓰레드를 Main thread 라고 한다. 싱글 쓰레드의 경우, 메인 쓰레드가 끝나면 프로세스가 중지된다. 하지만 멀티 쓰레드일 경우, 메인 쓰레드가 끝나더라도 다른 동작하는 쓰레드가 종료되어야 프로세스가 종료된다.
Main thread는 아래에 하위 쓰레드를 갖을 수 있고, 그 하위 쓰레드도 각각 하위 쓰레드를 갖을 수 있다.
동기화
multi threads의 경우 자원에 쓰레드가 접근할때 여러 쓰레드가 동시에 접근을 시도하여 문제가 발생할 수 있다. 이러한 상황을 막기 위해 자원을 먼저 점유하면 해당 자원에 Lock을 걸고, 해당 자원을 사용하고 나면 다른 쓰레드가 해당 자원을 점유할 수 있도록 동기화를 지원하고있다.
synchronized 블록, 클래스를 사용하여 동기화를 설정할 수 있다.
아래 예제에 synchronized 블록이 없다면 interrupted로 들어갈 수 있다.
package livestudy.week.ten;
public class TempClass {
public void execute(String msg){
System.out.println("execute : " + msg);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.err.println("multiThread1 execute interrupted.");
}
System.out.println("end. "+ msg);
}
}
package livestudy.week.ten;
public class MultiThreadMain {
public static void main(String[] args) {
TempClass c1 = new TempClass();
PracticeThread2 t1 = new PracticeThread2("a", c1);
PracticeThread2 t2 = new PracticeThread2("b", c1);
t1.start();
t2.start();
try {
t1.join();
t2.join();
} catch (InterruptedException e) {
System.err.println("interrupted");
}
}
}
class PracticeThread2 extends Thread{
private String m;
TempClass clazz;
PracticeThread2(String m, TempClass clazz){
this.m = m;
this.clazz = clazz;
}
@Override
public void run() {
synchronized (m) {
clazz.execute(m);
}
}
}
데드락(DeadLock)
멀티 쓰레드 프로그래밍에서 동기화를 통해 락을 획득하여 동일한 자원을 여러곳에서 사용하는 것에 대한 규칙을 정했다. 하지만 두 개 이상의 쓰레드에서 서로 가지고 있는 락이 해제 되기를 기다리며 무한이 대기상태에 빠지게 되는 경우가 있으며, 이를 데드락이라고 한다.
DeadLcok의 발생조건을 알아보자
- 상호 배체(Mutual Exclusion)
- 점유와 대기(Hold and Wait)
- 비선점(Non Preemptive)
- 환형대기(Circle Wait)
참고
백기선의 자바 스터디 :https://github.com/whiteship/live-study
http://tcpschool.com/java/java_thread_concept
https://www.geeksforgeeks.org/main-thread-java/
'Programming Language > java' 카테고리의 다른 글
[whiteship_java_study] 12주차 - 애노테이션(annotaion) (0) | 2021.09.07 |
---|---|
[whiteship_java_study]11주차. Enum (0) | 2021.08.26 |
[whiteship_java_study]9주차. 예외 처리 (0) | 2021.08.07 |
[whiteship_java_study]8주차. 인터페이스 (0) | 2021.08.05 |
[whiteship_java_study]7주차. 패키지 (0) | 2021.07.29 |