1. 스레드와 멀티스레딩
- 스레드 : 독립적으로 작업을 실행하는 단위. 한 스레드로 하나의 작업만 처리 가능. 응용프로그램 내의 자원과 메모리 공유.
- 멀티스레딩 : 작업 개수만큼 스레드 생성. 다수의 스레드를 가지고 다수의 작업을 동시 처리. 한 스레드가 대기하는 동안 다른 스레드 실행.
[JVM과 멀티스레드]
하나의 JVM(자바가상기계)는 하나의 자바 응용프로그램만 실행.
각 자바 응용프로그램은 별개의 메모리 영역에서 독립적으로 실행되고, 하나 이상의 스레드를 가질 수 있음(멀티스레딩).
2개 이상의 자바 응용프로그램이 서로 정보 주고받으려면 소켓통신같은 통신방법 이용.
2. 스레드 만들기
- Thread 클래스 이용하는 방법
- Runnable 인터페이스 이용하는 방법 (일반적)
[Thread 클래스 메소드]
Thread 클래스 경로명 : java.lang.Thread (java.lang패키지이므로 import 안해도 자동 import됨)
[Thread 클래스로 스레드 만들기]
1. 스레드 클래스 상속 & run() 코드 작성
- Thread 클래스 상속받아 클래스 작성
- run()메소드에 작성된 코드 : 스레드 코드
- 스레드는 run()부터 실행 시작. run() 종료시 스레드 종료됨
class TimerThread extends Thread { // Thread 클래스 상속
@Override
public void run(){ // run() 오버라이딩
...
}
}
2. 스레드 객체 생성
TimerThread th = new TimerThread(); // 스레드 객체 생성
3. 스레드 시작
start() 메소드 호출 → JVM에 의해 run()메소드 호출 (실행시작)
th.start();
4. 전체코드:
class TimerThread extends Thread { // Thread 클래스 상속
int n = 0;
@Override
public void run() { // run() 오버라이딩
while(true) {
System.out.println(n);
n++;
try {
Thread.sleep(1000); // 1초(1000ms)동안 잠자기
} catch(InterruptedException e) { return; }
}
}
}
public class TestThread {
public static void main(String args[]) {
TimerThread th = new TimerThread();
th.start();
}
}
* sleep()하는 동안 JVM은 다른 스레드 실행시킴
* sleep()하는 동안 발생할 예외처리 블록 가지고 있어야 함 (try-catch 블록 필수)
[Runnable 인터페이스로 스레드 만들기]
// Runnable 인터페이스
interface Runnable {
public void run(); // 추상메소드 run()하나만 가짐
}
1. 스레드 클래스 선언 & run() 코드 작성
class TimerRunnable implements Runnable { // Runnable 인터페이스 구현
@Override
public void run() { // run() 오버라이딩
...
}
}
2. 스레드 객체 생성
TimerRunnable 객체는 스레드 코드로 작동할 run()이 구현된 객체, th는 스레드 객체.
스레드 객체 생성시 TimerRunnable 객체 전달함
Thread th = new Thread(new TimerRunnable()); // 스레드 객체 생성
3. 스레드 시작
th.start();
4. 전체 코드:
class TimerRunnable implements Runnable { // Runnable 인터페이스 구현
int n = 0;
@Override
public void run() { // run() 오버라이딩
while(true) {
System.out.println(n);
n++;
try {
Thread.sleep(1000); // 1초(1000ms)동안 잠자기
} catch(InterruptedException e) { return; }
}
}
}
public class TestRunnable {
public static void main(String args[]) {
Thread th = new Thread(new TimerRunnable());
th.start();
}
}
3. 스레드 상태, 우선순위
[스레드 상태]
· NEW : 스레드 탄생. 실행준비안됨
· RUNNABLE : 스레드가 실행준비되어 스케줄링 기다리는 상태이거나, 실행중인 상태
· TIMED_WAITING : 스레드가 sleep() 호출해서 잠 자는 상태
· BLOCK : 스레드가 I/O작업 실행해서 I/O작업 완료 기다리면서 멈춘 상태.
· WAITING : 스레드가 wait()을 호출해서, 다른 스레드가 notify()를 부를 때까지 무한정 대기
· TERMINATED : 스레드 종료 상태
[스레드 우선순위]
스레드 우선순위 체계:
· 최댓값 = 10
· 최솟값 = 1
· 보통값 = 5 (main 스레드)
우선순위 값 바꾸려면 setPriority() 메소드 이용
void setPriority(int newPriority) // newPriority로 스레드의 우선순위 값 변경
4. 스레드 종료
[스스로 종료]
run() 메소드가 리턴 시 종료
public void run() {
...
return; // 스레드 스스로 종료
...
}
[강제 종료]
한 스레드에서 interrupt() 메소드 호출해 다른 스레드 강제 종료시키기
* interrupt를 받는 스레드의 catch 블록에 return;이 있어야 종료됨
public static void main(String args[]) {
TimerThread th = new TimerThread();
th.start();
th.interrupt(); // TimerThread 강제 종료
}
[flag 이용한 강제 종료]
finish() 메소드와 flag 필드를 만들고, 한 스레드에서 finish() 메소드 호출해 다른 스레드 강제 종료시키기
class TimerThread extends Thread {
private boolean flag = false; // false로 초기화
public void finish() { flag = true; } // finish 메소드 생성
@Override
public void run() {
while(true) {
...
if(flag == true) return; // flag가 true이면 스레드 종료
...
}
}
}
public static void main(String args[]){
...
th.finish(); // TimerThread 강제 종료
}
5. 스레드 동기화
· synchronized : 동기화 블록 지정
· wait() - notify() : 스레드 실행 순서 제어
[ synchronized 키워드 ]
순차 실행 제어
임계구역 지정. 다른 스레드는 lock 풀릴 때까지 대기.
↓ 한 스레드가 임계영역 블록 실행을 마칠 때까지 다른 스레드는 대기해야 함.
// 메소드 전체를 임계구역으로
synchronized void add(){
...
}
// 코드 블록을 임계구역으로
void add() {
synchronized(this) { // this 대신 다른 객체의 레퍼런스 사용가능
...
}
}
[ wait() - nodify() ]
- producer - consumer 문제 해결.
- 한 스레드가 공유데이터에 대해 lock을 소유하고 있으면, 1) 공유데이터에 접근하려는 다른 스레드는 wait()를 호출해 대기하고, 2) 현재 lock을 소유한 스레드가 작업을 마친뒤 notify()를 호출해서 3) 대기중인 스레드를 깨워준다.
· wait() : 다른 스레드가 notify() 불러줄 때까지 대기
· notify() : 대기중인 스레드 깨워 RUNNABLE 상태로. 오직 한 개의 스레드만 깨움
· notifyAll() : 대기중인 모든 스래드 깨워 RUNNABLE 상태로.
* 위 메소드를 호출하는 코드는 synchronized로 지정돼있어야 함.
synchronized public void fill() { // synchronized 키워드
if(barSize == maxBarSize) {
try {
wait(); // 조건을 만족하면 대기
} catch(InterruptedException e) {return;}
}
...
notify(); // 기다리는 스레드 깨우기
}
명품 JAVA Programming 참고
'개념 정리 > Java' 카테고리의 다른 글
[JAVA] 빠른 입출력 (BufferedReader, BufferedWriter, StringBuilder), 문자열 분리 (0) | 2024.02.21 |
---|---|
[JAVA] 네트워크, 소켓통신 (2) | 2024.01.07 |
[JAVA] 그래픽 (1) | 2023.10.26 |
[JAVA] 스윙 컴포넌트(JLabel, JButton, JCheckBox, JRadioButton, JTextField, JList, JComboBox) (0) | 2023.10.26 |
[JAVA] 이벤트, 리스너, key 이벤트, 마우스 이벤트 (0) | 2023.10.25 |