▶ 프로그램
- 어떤 작업(프로세스)을 실행할 수 있는 파일(cpu로 자원을 할당받지 않은 상태)
▶ 프로세스
- 현재 동작하고(실행되고) 있는 프로그램(작업을 위해 cpu로부터 자원을 할당받음)
▶ 스레드
- 한 개의 프로세스(process)내에서 실제로 작업을 수행하는 단위
- 모든 프로세스에는 한 개 이상의 스레드가 존재하여 작업을 수행한다.
※ 모든 자바 어플리케이션은 Main Thread가 main메서드를 실행하면서 시작된다.
■ 스레드의 특징
1. 메인스레드가 종료되더라도 실행 중인 스레드가 하나라도 있다면 프로세스는 종료되지 않는다.
=> 주종관계가 명확히 설정되어있지 않았을 때 발생하는 특징
2. 각 스레드의 실행시점을 결정해 주는 스케쥴러가 따로 있기 때문에 매번 결과가 다르게 보인다.
3. 멀티스레드 환경에서는 모든 작업이 동시에 일어나는 것처럼 보이지만 한 번에 하나의 스레드만 실행되고 있다.
a 스레드가 실행 => a 스레드가 멈춤 => b 스레드가 실행 => b 스레드가 멈춤 => c 스레드가 실행 => c 스레드가 멈춤 => a 스레드가 실행 => 이 과정 자체가 순식간에 발생하기 때문에 우리 눈에는 동시에 프로그램이 돌아가고 있는 것처럼 보인다.
※ 스레드는 동시에 여러 작업을 하는 것처럼 보이지만 최종적으로 걸리는 시간은 차이가 없다.
● 컴퓨터의 특징
1. 프로그램이라는 녀석을 실행하기 위해서는 cpu자원을 할당받아야 한다.
따라서 스레드가 프로그램을 실행하기 위해 CPU자원을 넘겨받고 스레드별로 실행시키기 위해 스케쥴러에게 자원을 빼앗긴다. 그렇기 때문에 명령어가 연속적으로 수행되지 못하고 어느 부분까지 수행하고 있었는지를 스레드 개별적으로 기억할 필요가 있다.(Register에 기록)
그리고 개별적인 실행흐름을 보장하기 위해 각 스레드별로 Stack메모리영역을 할당받는다.
※ Register : 스레드가 어느 명령어를 처리하고 있는지 그 주소값을 저장하고 있다.
▶ 멀티 스레드
- 한 개의 프로그램을 실행하고 그 내부적으로 여러 작업(스레드)을 처리하는 것
■ 멀티 스레드의 특징
4. 자원자체를 논리적으로 효율적으로 쓸 수 있다.
5. 하드웨어적인 한계 때문에 단일 스레드로 작업한다면 하드웨어의 수명이 금방 다한다. 때문에 스레드는 여러 개 있는 게 좋다.
■ 멀티 스레드의 장점
1) 자원을 보다 효율적으로 사용할 수 있다.
2) 사용자 입장에서 일처리가 빠르게 보인다.
3) 작업이 분리되어 코드가 간결해진다.
■ 스레드 생성 방법
1. Thread클래스를 상속받기
- Thread클래스 상속 후에 run()메서드 오버라이딩 => 스레드가 실행시키는 코드 내용이 run메서드 안의 내용
- Thread1 객체 생성 후 start() 메서드 호출
public class Thread1 extends Thread {
@Override
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.println(getName() + "[" + i + "]");
}
}
}
스레드 실행 시 (start() 호출 시) run()메서드가 자동으로 호출된다.
따라서 내가 작업하고자 하는 코드를 반드시 run이라는 메서드 안에 작성을 해야 한다.
즉, Thread클래스 안에 있는 run메서드를 내가 원하는 형태로 재정의하면 된다.
2. Runnable 인터페이스 구현하기
- Runnable 인터페이스 run() 메서드만 오버라이딩
- Thread 객체 생성 시 생성자에 Runnable 인터페이스를 구현한 구현 객체를 매개값으로 전달 후 start() 메서드 호출
public class Thread2 implements Runnable {
@Override
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.println(Thread.currentThread().getName() + "[" + i + "]");
}
}
}
※ Runnable 인터페이스를 구현하여 구현메서드만 따로 만드는 것을 권장한다.
3. 1회용 스레드가 필요할 때 사용(익명클래스)
굳이 클래스를 만들 필요 없이 1회용으로만 만들고자 할 때 사용된다.
public class Run {
public static void main(String[] args) {
Thread th3 = new Thread() {
@Override
public void run() {
for (int i = 1; i <= 5; i++) {
System.out.println(getName() + "[" + i + "]");
}
}
};
th3.setName("스레드 3"); // 스레드 이름 변경메서드
th3.start();
}
}
<결과>
스레드 3[1]
스레드 3[2]
스레드 3[3]
스레드 3[4]
스레드 3[5]
▶ 스레드 우선순위 설정
- 변경 전 스레드는 기본적으로 1 ~ 10 사이의 우선순위 중 5의 우선순위를 가지고 있다.
- 스레드의 우선순위를 정해주지 않으면 os가 임의로 수행시키며 메모리가 모자랄 때 우선순위를 정할 수 있다.
setPriority() : 우선순위를 지정해 주는 메서드
Thread th = new Threaad();
th.setPriority(Thread.MAX_PRIORITY); // 10
th.setPriority(Thread.MIN_PRIORITY); // 1
Thread.MAX_PRIORITY는 우선순위값 10을 반환해 준다.
Thread.MIN_PRIORITY는 우선순위값 1을 반환해 준다.
※ 우선순위는 10이 제일 우선이고 1이 제일 뒤다.
■ 주종관계 설정
main스레드가 종료 시 다른 스레드도 종료시키기 위해서는 반드시 setDaemon을 사용한다.
※ 스레드 중 한 개라도 setDaemon을 적용되었다면 모든 스레드에도 적용시켜야 한다.
■ 스레드 경쟁상태
하나의 공유자원에 동시에 여러 개의 스레드가 접근하는 상황을 경쟁상태라고 부른다.
이를 방지하기 위해 하나의 공유자원에 접근할 때는 하나의 스레드만 접근할 수 있도록 통제해야 한다.
통제가 필요한 영역을 임계영역이라고 부르며 임계영역을 통제하기 위하여 synchronized키워드(동기화)를 추가해야 한다.
▶ 동기화
- 멀티스레드 프로그래밍에서 스레드 간에 공유자원에 대한 처리를 말한다. 즉, 공유자원 사용순서를 정해주는 개념이다.
- 공유자원에 대한 LOCK을 획득한 스레드만 공유자원 사용이 가능하다.
■ synchronized (격리공간으로 지정)
- 동기화 메서드, 동기화 블럭에 사용되는 키워드
- 동기화 메서드는 메서드 선언에 synchronized키워드를 붙이고 인스턴스, 정적메서드 어디서든 사용이 가능하다.
- 동기화 메서드는 스레드가 메서드를 실행하면 메서드 전체에 락을 걸고 메서드가 종료되면 락이 풀린다.
public synchronized void method() {
}
- 현재 메서드가 존재하는 객체가 아니라 다른 객체에 락을 걸고 싶다면 동기화 블럭을 사용하면 된다. (동기화블럭 사용을 권장한다.)
동기화 블럭
[표현법]
synchronized(공유객체) {}
public void method() {
synchronized(this) {
}
}
'JAVA' 카테고리의 다른 글
JAVA (31) Network (0) | 2023.04.20 |
---|---|
JAVA (29) 제네릭(Generic) (0) | 2023.04.19 |
JAVA (28) Collection (0) | 2023.04.15 |
JAVA (27) 보조 스트림 (0) | 2023.04.15 |
JAVA (26) FileCharDao (0) | 2023.04.15 |