본글은 'Do it 자바 완전 정복' 책을 통한 공부내용을 정리한 글입니다.
이제 생성한 쓰레드의 객체를 참조하거나 우선순위를 지정하는 것과 같은 쓰레드의 속성 종류와 활용하는 방법을 알아본다.
현재 쓰레드 객체 참좃값 얻어오기
Thread 클래스를 직접 정의하고 객체를 생성해 사용할 때 참조 변수를 이용해 언제든지 쓰레드 객체의 속성(이름 등)을 가져올 수 있다.
하지만 직접 쓰레드 객체를 생성했을 때가 아니라(자바의 쓰레드 풀, main 쓰레드 등) 객체를 생성할 때 참조 변수를 정의하지 않을 경우에는 new Thread().start() 객체를 참조할 수 없게 된다. 이처럼 쓰레드 객체를 참조할 수 없을때 Thread 클래스의 정적 메서드, currentThread()
를 이용해 현재 쓰레드 객체의 참좃값을 가져올 수 있다.
static Thread Thread.currentThread()
실행 중인 쓰레드의 개수 가져오기
여러 개의 쓰레드가 실행되고 있을 때에 현재 실행(active) 중인 쓰레드의 개수를 알고자 한다면 activeCount()
메서드를 사용한다. 동일한 그룹 내에서 실행 중인 쓰레드의 개수를 리턴한다. 하나의 쓰레드에서 별도의 지정 없이 새로운 쓰레드를 생성하면 생성된 쓰레드는 동일한 쓰레드 그룹에 위치한다.
static int Thread.activeCount()
쓰레드의 이름 지정 및 가져오기
쓰레드를 구분하는 가장 손쉬운 방법은 쓰레드마다 이름을 부여하는 것이다. Thread 클래스의 인스턴스 메서드인 setName()
을 사용한다. 이름을 직접 지정하지 않으면 컴파일러가 자동으로 부여하며 thread-0, thread-1과 같이 'thread-숫자'의 형태로 부여된다.
String setName(String name)
해당 메서드는 인스턴스 메서드이므로 쓰레드 객체를 생성한 후에 적용할 수 있다. 쓰레드의 이름을 가져올 때에는 getName()
메서드를 사용한다.
public class ThreadProperties {
public static void main(String[] args) {
Thread curThread = Thread.currentTread();
System.out.println(curThread.getName()); // main
System.out.println(Thread.activeCount()); // 1
// 쓰레드 이름 자동 지정
for (int i = 0 ; i < 3 ; i++) {
Thread thread = new Thread();
System.out.println(thread.getName());
thread.start();
}
// 쓰레드 이름 직접 지정
for (int i = 0 ; i < 3 ; i++) {
Thread thread = new Thread();
thread.setName(i + "번 쓰레드");
System.out.println(thread.getName());
thread.start();
}
// 쓰레드 이름 자동 지정
for (int i = 0 ; i < 3 ; i++) {
Thread thread = new Thread();
System.out.println(thread.getName()); // Thread-4, Thread-5, Thread-6
thread.start();
}
System.out.println(Thread.activeCount()); // 4
}
}
쓰레드의 우선순위
모든 쓰레드는 1~10 사이의 우선순위를 갖고 있다. (1이 가장 낮고, 10이 가장 높음) 우선순위를 지정하지 않으면 기본값으로 5의 우선순위를 가진다.
우선순위는 쓰레드의 동시성과 관계가 있다. 2개의 작업이 하나의 CPU 코어에서 동작할 때 2개의 작업은 일정 간격으로 번갈아가며 실행되는데, 이때 우선 순위가 높으면 상대적으로 더 많은 시간을 할당받게 된다.
// 쓰레드 객체의 우선순위 정하기
void setPriority(int priority);
// 쓰레드 객체의 우선순위 가져오기
int getPriority();
아래는 예시코드다
class MyThread extends thread {
@Override
public void run() {
for(long i = 0 ; i < 100000000 ; i++) {} // 시간 지연용 반복문
System.out.println(getName() + getPriority());
}
}
public class ThreadProperties2 {
public static void main(String[] args) {
// 현재 컴퓨터의 CPU 코어 수 리턴 메소드
System.out.println(Runtime.getRuntime().availableProcessors());
for (int i = 0 ; i < 3 ; i++) {
Thread thread = new MyThread();
thread.start();
}
try {Thread.sleep(1000);} catch (InterruptedException e) {}
for(int i = 0 ; i < 10 ; i++) {
Thread thread = new MyThread();
thread.setName(i + "번 쓰레드");
// 가장 마지막에 실행된 쓰레드 객체에 가장 높은 우선순위 10 부여
if (i == 9) thread.setPriority(10);
thread.start();
}
}
}
주의사항은 쓰레드는 실제로 실행되기 전에 일정의 준비 과정(메모리의 할당 등)이 필요하므로 쓰레드의 실행 시간이 매우 짧을 때에는 실행 결과가 다르게 나올 수 있다. 즉, 우선순위가 가장 높아도 이 쓰레드가 시작되기 전에 앞의 쓰레드가 이미 종료될 수도 있다는 의미이다.
이때에는 예시코드 처럼 쓰레드의 지연 시간을 증가시키면 우선순위에 따른 결과를 얻을 수 있을 것이다.
쓰레드의 데몬 설정
일반적으로 쓰레드 객체를 실행하면 다른 쓰레드의 종료 여부와 관계 없이 자신의 쓰레드가 종료될 때 까지 계속 실행된다. 따라서 실행된 쓰레드가 무한 반복 쓰레드라면 해당 프로세스는 영원히 종료되지 않을 것이다.
하지만 해당 쓰레드를 생성해 실행한 주 쓰레드를 포함해 다른 쓰레드가 종료되면 남아있는 작업이 있다 하더라도 종료되어야 할 때가 있다. (ex: 문서 편집 프로그램 자체가 종료되면 자동 저장 쓰레드는 같이 종료) 일반 쓰레드가 모두 종료되면 함께 종료되는 쓰레드를 데몬 쓰레드(daemon thread)라 한다.
정리해 일반 쓰레드(non-daemon thread)는 다른 쓰레드 종료 여부와 상관 없이 자신의 작업이 종료 될때 까지 계속 수행하며, 데몬 쓰레드는 일반 쓰레드(사용자 쓰레드)가 모두 종료되면 작업이 완료되지 않았더라도 종료되는 것이다.
쓰레드의 데몬 설정은 Thread 클래스의 인스턴스 메서드 setDeamon()
로, 기본값은 false다.
void setDeamon(boolean on)
데몬 설정은 반드시 쓰레드를 실행하기 전(start()
메서드 호출 전)에 해야한다. 쓰레드가 실행된 이후에는 데몬 설정을 바꿀 수 없다.
생성한 객체의 데몬 설정 여부는 Thread 클래스의 인스턴스 메서드 isDeamon()
으로 확인할 수 있다.
boolean isDaemon()
아래는 예시코드다
class MyThread extends Thread {
@Override
public void run() {
for (int i = 0 ; i < 6 ; i++) {
System.out.println(getName() + i + "초");
// thread2 0초, thread2 1초, thread2 2초, thread2 3초 까지만 실행
try {Thread.sleep(1000);} catch(InterruptedException e) {}
}
}
}
public class ThreadProperties3 {
public static void main(String[] args) {
Thread thread2 = new MyThread();
thread2.setDaemon(true); // 데몬 쓰레드 설정
thread2.setName("thread2");
thread2.start();
}
// 3.5초 후 main 쓰레드 종료
try {Thread.sleep(3500);} catch(InterruptedException e) {}
}
만약 MyThread 객체를 2개 생성해 하나는 일반 쓰레드, 하나는 데몬 쓰레드로 지정한다면? 데몬쓰레드는 자신을 실행한 main 쓰레드가 종료되는 3.5초 시점에 종료되지 않고 프로세스 내의 일반 쓰레드가 종료되어야 종료된다.
'Backend > JAVA' 카테고리의 다른 글
[JAVA] #15.5 쓰레드의 상태 (0) | 2023.07.15 |
---|---|
[Java] #15.4 쓰레드의 동기화 (0) | 2023.07.08 |
[JAVA] #15.1, 15.2 쓰레드, 쓰레드의 생성 및 실행 (0) | 2023.07.04 |
[Java] #14 예외 처리 (0) | 2023.06.30 |
[Java] #13 이너 클래스와 이너 인터페이스 (1) | 2023.06.06 |