
1. Thread
1-1. 프로세스(process)
1-2. Thread란?
하나의 프로세스 내부에서 독립적으로 실행되는 하나의 작업단위를 말하며, 세부적으로는 운영체제에 의해 관리되는 하나의 작업 혹은 테스크를 의미한다.
하나의 실행 흐름, 프로세스 내부에 존재
main() 실행문은 하나의 스레드
이외의 또다른 스레드를 만들려면 Thread 클래스를 상속하거나, Runnable 인터페이스를 구현해야 한다.
하나의 스레드는 하나의 코드 실행 흐름이기 때문에, 한 프로세스 ㅐ에 스레드가 2개라면 2개의 코드 실행 흐름이 생긴다는 의미다.
프로세스 : 스레드 = 공장 : 일꾼
싱글 스레드 프로세스 : 자원 + 일꾼(스레드)
멀티 스레드 프로세스 : 자원 + 일꾼(스레드) + 일꾼(스레드) + ...
1-3. 멀티 프로세스 vs 멀티 스레드
1-4. 멀티 스레드의 장단점
장점
-> 자원을 보다 효율적으로 사용할 수 있다.
-> 사용자에 대한 응답성이 향상이 된다.
-> 작업이 분리되어 코드가 간결해진다.
단점
-> 동기화에 주의해야 한다.
-> 교착상태(dead-lock)가 발생하지 않도록 주의해야 한다.
-> 각 스레드가 효율적이고 고르게 실행될 수 있게 해야 한다.
1-5. Thread 생성 주기
New -> Runnable -> Running -> Dead
start() run()
New : 스레드가 생성되었지만 스레드가 아직 실행 준비가 되지 않은 단계
Runnable : 스레드가 실행되기 위한 준비 단계
Running : 선택된 스레드가 실행되는 단계
Blocked : 스레드가 작업을 완수하지 못하고 잠시 작업을 멈추는 단계
1-6 Runnable(준비 상태)
1-7. Running(실행 상태)
1-8. Thread의 run()과 start()의 차이
start()
-> Thread가 생성되며, Thread가 시작되면 run() 메서드가 실행
-> 멀티스레드로 동작한다.
run()
-> Thread가 생성되지 않으며, 그냥 run() 메서드만 실행
-> 싱글스레드로 동작한다.
package thread;
public class Main03 {
public static void main(String[] args) {
// Runnable 인터페이스 객체 생성과
// 객체를 매개변수로 하여 스레드 객체 한번에 생성
Thread th1 = new Thread(new RunnableTest());
Thread th2 = new Thread(new RunnableTest());
// 동시에 똑같은 숫자가 나온다.
// th1.start();
// th2.start();
// 번갈아가면서 나옴
th1.run();
th2.run();
}
}
1-9. Thread 종료
Thread의 interrupt() 메서드는 스레드가 일시 정지 상태에 있을 때 interruptedException 예외를 발생시키는 역할을 한다.
이것을 이용하면 Thread의 run() 메서드를 정상 종료시킬 수 있다.
package thread;
public class ThreadInterruptTest extends Thread {
@Override
public void run() {
try {
for(int i=0; i<= 10; i++) {
Thread.sleep(1000);
System.out.println(Thread.currentThread().getName()+ " " + i + " 번째 수행");
}
} catch (InterruptedException e) {
e.printStackTrace();
System.out.println("스레드 종료");
// 스레드 함수 내에서 return 문을 통해서
// 종료 및 소멸시키는 방법이 가장 이상적
return;
}
}
}
package thread;
public class Main04 {
public static void main(String[] args) {
ThreadInterruptTest th = new ThreadInterruptTest();
th.start();
// 3초 후에 인터럽트
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
th.interrupt();
}
}
1-10. 멀티 스레드 주의사항
멀티스레드가 동시에 수행되면서 공유될 수 있을 때, 공유되는 부분은 상호 배타적으로 사용돼야 한다.
DeadLock 문제
-> 멀티스레드를 사용할 때 주의할 점 중의 하나로 프로그램에서 스레드를 잘못 만들면 프로그램의 수행이 이루어지지 않고 무한 수행하는 DeadLock을 만들 수 있다.
임계영역
-> 공유 자원을 사용하는 코드 영역을 임계영역이라고 한다.
-> 이 부분에서는 공유 자원을 동시에 수정할 수 없도록 상호 배타적으로 실행될 수 있도록 작성되어야 한다.
자바에서 상호배제 문제를 해결하는 방법
-> 자바는 한 순간에 하나의 스레드만 실행할 수 있는 synchronized method 제공
-> 공유 자원을 사용하는 영역을 synchronized(객체명)의 블록으로 지정