2020. 4. 28. 19:32ㆍ인프런/웹개발 코스 [JAVA 개발언어]
스레드
스레드는 프로세스내에서 실행되는 세부 작업 단위입니다. 프로세스가 하나 이상의 스레드를 사용한다면 멀티 스레드라고 부르게 됩니다. Thread를 만드는 방법은 Thread 클래스를 상속받는 방법과 Runnable인터페이스를 구현하는 방법이 있습니다.
- 프로세스: 운영체제에서 실행되는 하나의 프로그램 단위이다 (ex. 크롬, 한글, 엑셀)
- 스레드: 프로세스 내에서 실행되는 세부 작업 단위
동작하고 있는 프로그램을 프로세스(Process)라고 합니다. 보통 한 개의 프로세스는 한 가지의 일을 하지만, 이 스레드를 이용하면 한 프로세스 내에서 두 가지 또는 그 이상의 일을 동시에 할 수 있게 됩니다.
Thread
스레드는 가장 간단하게 다음과 같이 만들 수 있습니다.
public class Test01 extends Thread{
public void run() {
System.out.println("thread run.");
}
public static void main(String[] args) {
Test01 test = new Test01();
test.start();
}
}
Test클래스가 Thread 클래스를 상속했습니다. Thread 클래스의 run 메서드를 구현하면 위 예제와 같이 test.start() 실행 시 test객체의 run 메서드가 수행이 된다. (Thread 클래스를 extends 했기때문에 start 메소드 실행 시 run 메소드가 수행되는 것입니다. Thread 클래스는 start 실행 시 run 메소드가 수행되도록 내부적으로 코딩되어 있습니다.)
실행하면 위의 사진처럼 "thread run."이라는 문장이 출력될 것입니다. 하지만 위처럼 스레드가 하나인 경우에는 도대체 쓰레드가 어떻게 동작하고 있는지 알 수가 없습니다.
스레드의 동작을 확인할 수 있는 다음의 예제를 만들어 봅니다.
public class Test01 extends Thread{
int seq;
public Test01(int seq) {
this.seq = seq;
}
public void run() {
System.out.println(this.seq+" thread start.");
try {
Thread.sleep(1000);
}catch(Exception e) {
}
System.out.println(this.seq+" thread end.");
}
public static void main(String[] args)
{
for(int i=0; i<10; i++)
{
Thread t = new Test01(i);
t.start();
}
}
}
총 10개의 스레드를 실행시키는 예제입니다. 어떤 쓰레드인지 확인하기 위해서 쓰레드마다 생성자에 순번을 부여했습니다. 그리고 쓰레드 메서드(run) 수행 시 시작과 종료를 출력하게 했고 시작과 종료 사이에 1초의 간격이 생기도록(Thread.sleep(1000)) 작성했습니다. 그리고 main 메소드 종료 시 "main end."를 출력하도록 했습니다.
위의 사진처럼 결과가 나오게 됩니다. 0번 스레드부터 9번 스레드까지 순서대로 실행이 되지 않고 그 순서가 일정치 않은 것을 보면 스레드는 순서에 상관없이 동시에 실행된다는 사실을 알 수 있습니다. 더욱 재밌는 사실은 스레드가 종료되기 전에 main 메소드가 종료되었다는 사실입니다. main 메소드 종료 시 "main end."라는 문자열이 출력되는데 위 결과를 보면 중간쯤에 출력되어 있습니다.
Join
위 예제를 보면 쓰레드가 모두 수행되고 종료되기 전에 main 메소드가 먼저 종료되어 버렸습니다. 그렇다면 모든 쓰레드가 종료된 후에 main 메서드를 종료시키고 싶은 경우에는 어떻게 해야 할지 다음 예제를 통해 알아보겠습니다.
import java.util.ArrayList;
public class Test01 extends Thread{
int seq;
public Test01(int seq) {
this.seq = seq;
}
public void run() {
System.out.println(this.seq+" thread start.");
try {
Thread.sleep(1000);
}catch(Exception e) {
}
System.out.println(this.seq+" thread end.");
}
public static void main(String[] args)
{
ArrayList<Thread> threads = new ArrayList<Thread>();
for(int i=0; i<10; i++) {
Thread t = new Test01(i);
t.start();
threads.add(t);
}
for(int i=0; i<threads.size(); i++) {
Thread t = threads.get(i);
try {
t.join();
}catch(Exception e) {
}
}
System.out.println("main end.");
}
}
생성되는 스레드를 담기 위해서 ArrayList 객체인 threads를 만든 후 쓰레드 생성 시 생성된 객체를 threads에 저장합니다. main 메서드가 종료되기 전에 threads에 담긴 각각의 thread에 join 메서드를 호출하여 스레드가 종료될 때까지 대기하도록 변경하였습니다.
여기서 ArrayList를 사용하기 위해서는 클래스 상단에 import java.util.ArrayList; 로 ArrayList를 먼저 import 해야 합니다.
스레드의 join 메서드는 스레드가 종료될 때까지 기다리게 하는 메서드입니다. 위와 같이 변경한 후 프로그램을 수행하면 다음과 같은 결과가 나옵니다.
main end라는 문자열이 가장 마지막에 출력되는 것을 확인할 수 있습니다.
스레드 프로그래밍 시 가장 많이 실수하는 부분이 바로 스레드가 종료되지 않았는데 쓰레드가 종료된 줄 알고 그다음 로직을 수행하게 만드는 일입니다. 쓰레드가 종료된 후 그 다음 로직을 수행해야 할 때 꼭 필요한 것이 바로 이 join 메서드입니다.
Runnable
보통 스레드 객체를 만들 때 위의 예처럼 Thread를 상속하여 만들기도 하지만 보통 Runnable 인터페이스를 구현하도록 하는 방법을 많이 사용합니다.
위에서 만든 예제를 Runnable 인터페이스를 사용하는 방식으로 변경해 봅니다.
import java.util.ArrayList;
public class Test01 implements Runnable{
int seq;
public Test01(int seq) {
this.seq = seq;
}
public void run() {
System.out.println(this.seq+" thread start.");
try {
Thread.sleep(1000);
}catch(Exception e) {
}
System.out.println(this.seq+" thread end.");
}
public static void main(String[] args)
{
ArrayList<Thread> threads = new ArrayList<Thread>();
for(int i=0; i<10; i++) {
Thread t = new Thread(new Test01(i));
t.start();
threads.add(t);
}
for(int i=0; i<threads.size(); i++) {
Thread t = threads.get(i);
try {
t.join();
}catch(Exception e) {
}
}
System.out.println("main end.");
}
}
Thread를 extends 하던 것에서 Runnable을 implements 하도록 변경되었습니다. (Runnable 인터페이스는 run 메서드를 구현하도록 강제합니다.) 그리고 Thread를 생성하는 부분을 다음과 같이 변경했습니다.
Thread t = new Thread(new Test01(i));
결과 값이 같은 걸 볼 수 있습니다.
Thread의 생성자로 Runnable 인터페이스를 구현한 객체를 넘길 수 있는데 이 방법을 사용한 것입니다. 이렇게 변경된 코드는 이 전에 만들었던 예제와 완전히 동일하게 동작합니다. 하지만 인터페이스를 이용했으니 상속 및 기타 등등에서 좀 더 유연한 프로그램으로 발전했다고 볼 수 있습니다.
'인프런 > 웹개발 코스 [JAVA 개발언어]' 카테고리의 다른 글
싱글톤 패턴 (0) | 2020.04.28 |
---|---|
stream (0) | 2020.04.28 |
Collection (0) | 2020.04.28 |
열거형 (0) | 2020.04.27 |
내부 클래스 (0) | 2020.04.27 |