스레드(Thread)와 멀티스레드(Multi Thread) 구현
1. Thread 란?
하나의 프로세서 안에서 독립적으로 실행되는 작은 실행 단위로, 프로그램의 명령을 실행하게끔 해주는 소프트웨어적인 실행 주체이다. 개발자가 별도의 Thread를 생성하지 않는다면, 한 프로그램에 하나의 스레드가 존재하여 해당 명령을 차례차례 순서대로 실행시킨다.
자바에서는 스레드를 통해 한 번에 여러가지 일을 동시적으로 처리할 수 있게 지원한다.
기본적인 스레드 형태부터 알아보자.
class ThreadA1 extends Thread{
public void run() {
// 오버라이딩
}
}
Thread의 선언은 동시에 처리할 클래스에 Thread 클래스를 상속하는 것부터 시작한다. Thread 상속한 클래스에는 run() 메소드가 존재하는데, Thread 호출 시 run() 안의 코드가 실행된다. 따라서 동작할 코드를 작성해 run 메소드를 오버라이딩 한다.
ThreadA1 a1 = new ThreadA1();
a1.start();
이후 해당 Thread를 호출할 클래스에서 Thread 객체를 생성하고, run() 메소드를 실행하기 위해 .start() 를 호출한다.
thread 클래스는 내부적으로 start() 메소드를 실행할 때 run() 메소드가 수행되도록 동작한다.
아래는 1부터 10까지의 숫자를 반복 실행하는 ThreadA1 클래스와 ThreadA2 클래스가 있다. ThreadA1 클래스는 Thread를 상속해주었고, ThreadA2는 일반 클래스이다.
class ThreadA1 extends Thread{
public void run() {
for(int i=1; i<=10; i++)
System.out.println("ThreadA1 : " + i);
}
}
Thread 클래스를 상속한 ThreadA1 클래스
class ThreadA2{
public void run() {
for(int i=1; i<=10; i++)
System.out.println("ThreadA2 : " + i);
}
}
ThreadA2 클래스
public static void main(String[] args) {
ThreadA1 a1 = new ThreadA1();
ThreadA2 a2 = new ThreadA2();
a1.start(); // 스레드 run() 메소드 호출
a2.run(); // 일반 메소드 호출
}
main 메소드
a1 객체를 우선적으로 호출했음에도 Thread 객체와 일반 클래스 객체가 뒤죽박죽 출력된 것을 확인할 수 있다. 결과를 호출할 때마다 이 순서는 바뀌게 된다. 이처럼 Thread는 순서와 상관없이 다른 명령과 동시에 실행됨을 알 수 있다.
2. 멀티스레딩 구현
두 개 이상의 Thread가 동시 실행되는 방식을 멀티스레드(multi thread)라고 한다. 자바에서 프로그램 실행 중 동시처리하고자 하는 작업이 있다면 원래 갖고 있는 Thread 외에 별도의 Thread를 추가해서 사용할 수 있다.
멀티스레딩을 구현하는 방법은
- Thread 추가가 필요한 클래스에 Thread 클래스를 상속 받는다.
- Thread 클래스에 존재하는 run() 메소드를 상속받은 클래스에서 실행하고자 하는 코드들로 오버라이드한다.
- 멀티스레딩을 발생시킬 클래스에 Thread 객체를 생성한다.
- run() 메소드의 코드들이 별도의 스레드에서 실행되게 하기 위해 start() 메소드를 호출한다.
로 앞서 다뤘던 Thread 구현 방법과 같다. (ㅎ) 다만 Thread 객체가 여러 개 인 것 뿐이다.
class ThreadB1 extends Thread {
public void run() {
for (int i = 1; i <= 10; i++) {
System.out.println("ThreadB1 : " + i);
try {
sleep(100); // 출력 0.1초 지연
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Thread 클래스를 상속하는 ThreadB1
class ThreadB2 extends Thread {
public void run() {
for (int i = 1; i <= 10; i++) {
System.out.println("ThreadB2 : " + i);
try {
sleep(100); // 출력 0.1초 지연
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
Thread 클래스를 상속하는 ThreadB2
public static void main(String[] args) {
ThreadB1 b1 = new ThreadB1();
ThreadB2 b2 = new ThreadB2();
b1.start();
b2.start();
for (int i = 1; i <= 10; i++) {
System.out.println("main : " + i);
try {
Thread.sleep(100); // 출력 0.1초 지연
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
main 메소드
각 클래스에 1부터 10까지 호출하는 출력문을 작성한 뒤, 출력될 때마다 0.1초씩 지연되도록 Thread.sleep(100); 을 작성해주었다. 해당 메소드는 예외처리가 필요한 구문으로 try-catch 문을 작성했다.
결과는 다음과 같다.
1부터 10까지 호출하는 동안에도 언제는 ThreadB1의 객체가, 언제는 ThreadB2의 객체가, 또 언제는 main이 먼저 실행되기도 했다. 해당 코드 역시 실행할 때마다 순서가 바뀐다. Thread 객체는 다른 코드가 실행되길 기다리지 않고, 동시에 실행하도록 돕기 때문에 이런 결과가 나타나게 된다.
3. 멀티스레드 활용 예제
10초 타이머가 흐르는 동안 팝업에 문자를 입력하면 타이머가 종료되고, 시간내에 입력하지 못하면 "타임오버"라는 문구가 뜨게 되면서 프로그램이 종료되는 예시다.
class ThreadD extends Thread{
private boolean state = true;
public void setState(boolean b) {
this.state = b;
}
public void run() {
// 시간이 10초가 지나거나, state 상태가 false가 되면 종료
for(int i=10; (i>=1) && (state == true); i--) {
System.out.println(i + "초 남았습니다");
try {
sleep(1000); // 1초씩 줄어드는 타이머를 표현하기 위함
} catch (InterruptedException e) {
e.printStackTrace();
}
// 해당 if문은 for문에 조건으로 넣음
//if(state == false) break; // 실행 중간에라도 끝내라
}
if(state == true) System.out.println("타임오버입니다");
}
}
Thread를 상속하는 ThreadD 클래스
public static void main(String[] args) {
ThreadD d = new ThreadD();
d.start();
String input = JOptionPane.showInputDialog("정답을 입력하세요.");
System.out.println("입력하신 값은 " + input + " 입니다.");
d.setState(false); // 값을 입력 받으면 state를 false로 설정
}
main 메소드
JOptionPane.showInputDialog 는 값을 입력 받고 저장하는 팝업 형태의 입력란이다.
시간 내에 문구를 입력하지 못하면 위와 같은 " 타임오버입니다 " 문구가,
시간 내에 문구를 입력하면 입력한 값을 출력하고, 타이머가 멈춘다.
'Backend > Java' 카테고리의 다른 글
[JAVA] BufferedReader 사용 이유와 과정 (read, 스트림(Stream), 버퍼(Buffer)) (0) | 2024.10.23 |
---|---|
[JAVA] 예외(Exception) 처리 (0) | 2024.10.22 |
[JAVA] 숫자 출력 형식 지정 DecimalFormat 클래스 (0) | 2024.10.21 |
[JAVA] 날짜 출력 형식 지정을 위한 SimpleDateFormat 클래스 (0) | 2024.10.21 |
[JAVA] 날짜와 시간 출력을 위한 Calendar, Date 클래스 (0) | 2024.10.20 |