Java (자바)

[Java] Thread (2) - 스레드 사용 예제 : 타이머 구현 / isAlive() 메서드

Oscar:) 2022. 7. 8. 20:17

 

지난 포스팅에 이어서 이번 시간에는,

멀티 스레드를 직접 사용해보며 공부해 볼 것이다.

 


 

 

자바에서 스레드를 생성하는 방법에는 2가지가 있다.

 

1. Thread 클래스를 상속받아서 사용

 

2. Runnable 인터페이스를 구현해서 사용

 

 


 

· 왜 2가지 방식으로 나눠서 사용할까?

 

자바에서는 단일 상속만을 허용하기 때문이다.

 

 

이미 다른 클래스를 상속받고 있는 클래스에서는

Thread 클래스를 상속받지 못한다.

 

그럴 때에는 Runnable 인터페이스에서 스레드를 구현해야 할 것이다.

 

 


 

두 가지 방식이지만, 스레드를 작성하는 방법은 동일하다.

 

스레드를 사용하고 싶은 내용을

run() 메서드 안에 작성해야 한다.

 

 

본인은 Thread 클래스를 상속받아서

타이머 기능을 하는 스레드를 만들어 보겠다.

 


 

먼저 두개의 클래스를 생성해 주겠다.

 

· Timer 클래스 : 스레드의 기능을 작성해준다.

 

· Play 클래스 : 해당 스레드를 실행할 main 메서드가 있는 클래스이다.

 

 

Timer.java

public class Timer extends Thread {

	public void run() {
		
	}
	
}

 

Thread 클래스를 상속해주었다.

 

위에서도 언급했듯이,

run() 메서드를 사용해야 한다.

 

 

 

Play.java

public class Play {

	public static void main(String[] args) {
		
		Timer timer = new Timer();
		
		timer.start();

	}

}

 

Timer 클래스를 호출하여 객체를 생성하고,

start() 메서드를 작성해주었다.

 

지금은 Timer 클래스에 작성한 내용이 없기에,

아무것도 실행되지 않는다.

 

 


sleep() 메서드를 작성해 준다.

 

Thread 클래스에는 다양한 메서드가 있다.

이번 포스팅에서는 sleep() 메서드를 사용해 보겠다.

 

 

Timer.java

public class Timer extends Thread {

	public void run() {
			
			Thread.sleep(1000);
            
	}
	
}

 

sleep 메서드는,

의미 그대로 해석하면 이해하기 쉽다.

(잠을 잔다. 즉, 지정된 시간 동안 기능을 멈춘다.)

 

sleep() 괄호 안에 1000은 1초를 의미한다.

(0.5초는 500, 2초는 2000으로 작성하면 된다)

 

 

하지만, 다음과 같이 에러가 표시될 것이다.

 

에러의 내용은 다음과 같다.

" 해당 문법을 사용하려면 try / catch 로 둘러싸라 "

 

그렇다.

자바에서 스레드를 사용하기 위해서는 try / catch 문이 강제된다.

 

빨간 줄이 표시된 부분을 클릭하면

try / catch 자동 완성 문구가 표시될 것이다.

 

 


 

try / catch 문을 추가해 준다.

 

Timer.java

public class Timer extends Thread {

	public void run() {
		
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
	}
	
}

 

 

처음 보는 강제되는 문법이라 부담될 수 있다.

하지만, 의미 그대로 해석하면 이해하기 쉽다.

 

● try : 시도하다

스레드를 시도하는 것이다.
해당 영역에서 작업할 내용을 작성하면 된다.

 

● catch : 잡다

- Interrupted : 중단되다
- Exception : 예외

예외 상황으로 인해 중단되었을 때 잡아준다.
(쉽게 말해, 에러가 발생했을 때 잡는다)

 

아무래도, 멀티 스레드의 사용은

불안정한 면이 존재한다.

 

때문에 try / catch 문을 강제하여

안정성을 잡아주는 느낌이 든다.

 

 


 

반복문 (for문) 을 작성해 준다.

 

반복문을 작성하는 위치는 사용하기 나름이다.

 

Timer.java  (try 영역 안에 for문 배치)

public class Timer extends Thread {

	public void run() {
		
		try {
			
			for (int i = 5; i >= 0; i--) {
			
				System.out.println("남은 시간 : " + i +"초");
				
				Thread.sleep(1000);
			
			} // 여기까지 for문
			
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
	} // run() 메서드
	
} // Timer 클래스

 

 

Timer.java  (for문 영역 안에 try/catch 배치)

public class Timer extends Thread {

	public void run() {
		
		for(int i = 5; i >= 0; i--) {
		
		try {
			
				System.out.println("남은 시간 : " + i +"초");
				
				Thread.sleep(1000);
			
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		} // for문
		
	} // run() 메서드
	
} // Timer 클래스

 

반복문을 작성한 위치만 다를 뿐,

둘 다 정상적으로 작동이 된다.

 

본인이 작성한 코드의 환경에 알맞게

적절히 배치하여 사용하기 바란다.

 

 

공통적인 핵심 내용은 다음과 같다.

 

5부터 0까지 1씩 작아지는 반복문을 작성한다.

반복문의 영역 안에는,
해당 값을 출력해주는 내용과
1초 씩 멈춰주는 sleep() 메서드가 담겨있다.

 

 

출력 결과는 다음과 같다.

 

정상적으로 잘 출력되는 것을 확인할 수 있다.

 

 

그런데, 남은 시간이 0초일 때는

"타이머 종료" 라는 텍스트가 출력됬으면 좋겠다.

 

 


 

조건문을 사용해 간단한 텍스트 수정.

 

 

Timer.java

public class Timer extends Thread {

	public void run() {
		
		try {
        
			for(int i = 6; i >= 0; i--) {
            
			if (i == 6) {
				System.out.println("☆ 타이머 시작 ☆\n");
			} else if (i > 0) {
				System.out.println("남은 시간 : " + i +"초");
			} else {
				System.out.println("\n★ 타이머 종료 ★");
			}
			
				Thread.sleep(1000);
			
            } // for문
            
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
	} // run() 메서드
	
} // Timer 클래스

 

조건문을 사용하여 살짝 커스텀 해 보았다.

 

위와 같이, 해당 스레드의 run() 메서드 내에서

여러 코드를 사용하여 이벤트를 만들어 줄 수 있다.

 

 

출력 결과는 다음과 같다.

 

 

 


 

isAlive() 메서드

 

 

Thread 클래스에서 제공해주는 메서드이다.

 

스레드가 동작하고 있는지, 아닌지를 boolean 값으로 리턴한다.

(스레드가 살아있는지, 죽었는지...메서드 이름을  정말 잘 지은 것 같다..)

 

 

Play.java

import java.util.Scanner;

public class Play {

	public static void main(String[] args) {
		
		Scanner scan = new Scanner(System.in);
		Timer timer = new Timer();
		
		timer.start();
		
		while (true) {
			
		scan.next();
		
		if (timer.isAlive()) {
			System.out.println("스레드 상태 : ● 살아있음 ●");
		} else {
			System.out.println("스레드 상태 : ● 죽었음 ●");
		}
		
		} // while(true)
		
	} // main 메서드

} // Play 클래스

 

위와 같이 isAlive() 메서드를 사용한다면,

해당 스레드가 동작 중일 때와 아닐 때를 구분하여

코드를 제어할 수 있게 된다.

 

(스레드를 사용하면 할 수록,

제어할 수 있는 함수가 있다는 게 정말 소중하다고 느낀다)

 

 

위의 코드를 간단하게 풀이하자면 다음과 같다.

 

자바 스캐너를 사용했다.

사용자가 값을 입력할 때만 반복문이 돌게 끔
while (true) 의 무한루프를 제어해 주었다.

next() 메서드이기 때문에,
사용자가 아무 값이나 입력하면
isAlive()의 결과 값을 확인할 수 있다.

 

 

 

출력 결과는 다음과 같다.

 

타이머 진행 중에 2번, 종료 후 1번 입력하였다.

 

isAlive() 메서드가 역할을 제대로 해내고 있는 것을 확인하였다.

 

 


 

 

 

이번 포스팅에서는

멀티 스레드를 직접 구현해 보았다.

 

처음 접할 때는 어려운 내용이지만,

배우고나면 활용도가 큰 개념이라고 생각한다.

 

 

지금도 종종 스레드로 무언가를 만들어낼 때면,

재미있다고 느낀다.