이 글은 유튜브 '자바의 정석 - 기초편'을 보고 정리한 글입니다.
●⚝
✎정리
⍟실습
📂content
1. main 스레드
- main메서드의 코드를 수행하는 스레드
- 스레드는 '사용자 스레드'와 '데몬 스레드' 두 종류가 있다.
=> 사용자 스레드는 main 스레드이고, 데몬 스레드는 보조 스레드이다.
실행 중인 사용자 스레드가 하나도 없을 때 프로그램은 종료된다.
즉, 멀티 스레드에서는 메인 메서드가 종료되었어도, 실행중인 스레드가 남아있다면 프로그램은 종료되지 않는다.
⍟실습
Ex13_11
class Ex13_11 {
static long startTime = 0;
public static void main(String args[]) {
ThreadEx11_1 th1 = new ThreadEx11_1();
ThreadEx11_2 th2 = new ThreadEx11_2();
th1.start();
th2.start();
startTime = System.currentTimeMillis();
try {
th1.join(); // main쓰레드가 th1의 작업이 끝날 때까지 기다린다.
th2.join(); // main쓰레드가 th2의 작업이 끝날 때까지 기다린다.
} catch(InterruptedException e) {}
System.out.print("소요시간:" + (System.currentTimeMillis() - Ex13_11.startTime));
} // main
}
class ThreadEx11_1 extends Thread {
public void run() {
for(int i=0; i < 300; i++) {
System.out.print(new String("-"));
}
} // run()
}
class ThreadEx11_2 extends Thread {
public void run() {
for(int i=0; i < 300; i++) {
System.out.print(new String("|"));
}
} // run()
}
결과
그런데 `try - catch` 부분을 주석 처리하고 돌리면
위와 같이 바로 소요시간이 찍힌다. main이 스레드를 2개를 만들고, 바로 소요시간을 출력하고 할 일이 없어서 종료되기 때문이다. 그 다음에 두 스레드가 번갈아 작업을 하다가 프로그램이 종료된 것이다.
2. 싱글스레드와 멀티스레드
- 싱글 스레드
class ThreadTest {
public static void main(String args[]) {
for(int i=0; i < 300; i++) {
System.out.println("-");
}
for(int i=0; i < 300; i++) {
System.out.println("|");
}
} //main
}
- 멀티스레드
class ThreadTest {
public static void main(String args[]) {
MyThread1 th1 = new ThreadEx11_1();
MyThread2 th2 = new ThreadEx11_2();
th1.start();
th2.start();
}
}
class MyThread1 extends Thread {
public void run() {
for(int i=0; i < 300; i++) {
System.out.print("-");
}
} // run()
}
class MyThread2 extends Thread {
public void run() {
for(int i=0; i < 300; i++) {
System.out.print("|");
}
} // run()
}
여기 그림은 스레드가 같은 시간을 동작하는 것 처럼 그려져 있지만 사실 이것은 os가 결정을 하기 때문에 그림과는 다르게 동작된다.
추가로 이 그림을 보면 싱글스레드의 종료된 시간보다 멀티스레드의 종료된 시간이 더 늦다.
그 이유는 A -> B / B -> A 작업의 바뀔 때(context switching) 시간이 좀 걸린다.
하지만 그럼에도 멀티스레드를 사용하는 이유는 두 가지 작업을 동시에 할 수 있다는 장점이 있기 때문이다.
마치 채팅하면서 사진이나 파일을 주고받는 것처럼 말이다. 그리고 또 다른 장점은 작업을 효율적으로 할 수 있다.
3. 스레드와 I/O 블락킹(blocking)
I : Input 입력
O : Output 출력
blocking : 막힘
즉, I/O 블락킹은 입출력시 작업이 중단되는 것을 말한다.
- 싱글 스레드
class ThreadEx6 {
public static void main(String[] args) {
//A. 입력받기
String input = JOptionPane.showInputDialog("아무 값이나 입력하세요.");
System.out.println("입력하신 값은 " + input + "입니다.");
//------------------------------------------------------------
//B. 카운트 다운
for(int i = 10; i > 0 ; i-- ) {
System.out.println(i);
try { Thread.sleep(1000); } catch(Exception e ) {}
}
} //main
}
위 코드는 사용자가 입력을 할 때까지 A에서 멈춘다. 그러면 프로그램은 정지상태가 된다.
그리고 사용자가 입력을 하고 카운트 다운이 시작되는 것이다.
위 코드를 멀티스레드로 바꿔보자!
- 멀티 스레드
class ThreadEx7 {
public static void main(String[] args) {
ThreadEx7_1 th1 = new ThreadEx7_1();
th1.start();
//A. 입력받기
String input = JOptionPane.showInputDialog("아무 값이나 입력하세요.");
System.out.println("입력하신 값은 " + input + "입니다.");
}
}
class ThreadEx7_1 extends Thread {
public void run() {
//B. 카운트 다운
for(int i = 10; i > 0 ; i-- ) {
System.out.println(i);
try { Thread.sleep(1000); } catch(Exception e ) {}
}
} //run()
}
똑같이 사용자로부터 입력을 기다리는 구간에서 스레드B가 실행이 된다. 그래서 싱글스레드보다 멀티스레드가 더 빨리 작업을 끝낼 수도 있다.
4. 스레드의 우선순위(priority of thread)
- 작업의 중요도에 따라 스레드의 우선순위를 다르게 하여 특정 스레드가 더 많은 작업시간을 갖게 할 수 있다.
void setPriority(int newPriority) //스레드의 우선순위를 지정한 값으로 변경한다.
int getPriority() //스레드의 우선순위를 반환한다.
public static final int MAX_PRIORITY = 10 // 최대우선순위
public static final int MIN_PRIORITY = 1 // 최소우선순위
public static final int NORM_PRIORITY = 5 // 보통우선순위
우선순위가 더 높은 스레드가 시간을 더 많이 할당 받는다. 그래서 결과적으로 우선순위가 더 높은 스레드가 더 빨리 끝날 가능성이 높다. 그런데 os는 이 우선순위를 참고만 하지 꼭 개발자의 마음대로 실행되지는 않는다.
스레드의 우선순위는 1~10까지 존재하며, 숫자가 클 수록 우선순위가 높다.
⍟실습
Ex13_6
class Ex13_6 {
public static void main(String args[]) {
ThreadEx6_1 th1 = new ThreadEx6_1();
ThreadEx6_2 th2 = new ThreadEx6_2();
th2.setPriority(7);
System.out.println("Priority of th1(-) : " + th1.getPriority());
System.out.println("Priority of th2(|) : " + th2.getPriority());
th1.start();
th2.start();
}
}
class ThreadEx6_1 extends Thread {
public void run() {
for(int i=0; i < 300; i++) {
System.out.print("-");
for(int x=0; x < 10000000; x++);
}
}
}
class ThreadEx6_2 extends Thread {
public void run() {
for(int i=0; i < 300; i++) {
System.out.print("|");
for(int x=0; x < 10000000; x++);
}
}
}
5. 스레드 그룹
- 서로 관련된 스레드를 그룹으로 묶어서 다루기 위한 것
- 모든 스레드는 반드시 하나의 스레드 그룹에 포함되어 있어야 한다.
- 스레드 그룹을 지정하지 않고 생성한 스레드는 'main스레드 그룹'에 속한다.
- 자신을 생성한 스레드(부모 스레드)의 그룹과 우선순위를 상속받는다.
스레드의 생성자
Thread(ThreadGroup group, String name)
Thread(ThreadGroup group, Runnable target)
Thread(ThreadGroup group, Runnable target, String name)
Thread(ThreadGroup group, Runnable target, String name, long stackSize)
ThreadGroup getThreadGroup() 스레드 자신이 속한 스레드 그룹을 반환한다.
void uncaughtException(Thread t, Throwable e) 처리되지 않은 예외에 의해 스레드 그룹의 스레드가 실행이 종료되었을 때, JVM에 의해 이 메서드가 자동적으로 호출된다.
6. 스레드 그룹의 메서드
메서드명 | 설명 |
ThreadGroup(String name) | 지정된 이름의 새로운 스레드 그룹을 생성 |
ThreadGroup(ThreadGroup parent, String name) | 지정된 스레드 그룹에 포함되는 새로운 스레드 그룹을 생성 |
int activeCount() | 스레드 그룹에 포함된 활성상태에 있는 스레드의 수를 반환 |
int activeGroupCount() | 스레드 그룹에 포함된 활성상태에 있는 스레드 그룹의 수를 반환 |
void checkAccess() | 현재 실행중인 스레드가 스레드 그룹을 변경할 권한이 있는지 체크 |
void destroy() | 스레드 그룹과 하위 스레드 그룹까지 모두 삭제한다. 단, 비어있어야 삭제 가능 |
int enumerate(Thread[] list) int enumerate(Thread[] list, boolean recurse) int enumerate(ThreadGroup[] list) int enumerate(ThreadGroup[] list, boolean recurse) |
스레드 그룹에 속한 스레드 또는 하위 스레드 그룹의 목록을 지정된 배열에 담고 그 개수를 반환. 두 번째 매개변수인 recurse의 값을 true로 하면 스레드 그룹에 속한 하위 스레드 그룹에 스레드 또는 스레드 그룹까지 배열에 담는다. |
int getMaxPriority() | 스레드 그룹의 최대우선순위를 반환 |
String getName() | 스레드 그룹의 이름을 반환 |
ThreadGroup getParent() | 스레드 그룹의 상위 스레드 그룹을 반환 |
void interrupt() | 스레드 그룹에 속한 모든 스레드를 interrupt |
boolean isDaemon() | 스레드 그룹이 데몬 스레드 그룹인지 확인 |
boolean isDestroyed() | 스레드 그룹이 삭제되었는지 확인 |
void list() | 스레드 그룹에 속한 스레드와 하위 스레드 그룹에 대한 정보를 출력 |
boolean parentOf(ThreadGroup g) | 지정된 스레드 그룹의 상위 스레드 그룹인지 확인 |
void setDaemon(boolean daemon) | 스레드 그룹을 데몬 스레드 그룹으로 설정/해제 |
void set MaxPriority(int pri) | 스레드 그룹의 최대 우선순위를 설정 |
출처
'🎥Back > 자바의 정석' 카테고리의 다른 글
[JAVA의 정석] 스레드와 관련된 함수 및 동기화 (0) | 2024.03.01 |
---|---|
[JAVA의 정석]데몬 스레드, 스레드의 상태 (0) | 2024.02.29 |
[JAVA의 정석]스레드 (0) | 2024.02.29 |
[JAVA의 정석]Object클래스와 equals() (0) | 2024.02.29 |
[JAVA의 정석]hashCode(), toString() (0) | 2024.02.28 |