Java에서 Thread는 프로세스 내에서 독립적으로 실행되는 작업 단위를 의미합니다. 이 글에서는 스레드의 기본 개념, 사용방법, 동시성(comcurrency) 문제 및 이를 해결하는 방법을 예제를 통해 살펴보겠습니다.
즉, 스레드는 프로세스 내에서 독립적으로 실행되는 하나의 작업 흐름입니다.
🧠 예시로 이해하기
하나의 웹 브라우저(프로그램) 안에서
한 탭(프로세스)에서 여러 다운로드가 동시(스레드)에 진행된다.
“하나의 웹 브라우저(프로그램) 안에서, 한 탭(프로세스)에서 여러 다운로드가 동시에 진행(스레드)된다.”
참고:
크롬 같은 최신 브라우저는 탭마다 별도의 프로세스를 사용하는 멀티 프로세스 구조입니다.
main
메서드는 기본적으로 하나의 스레드입니다.예를 들어, 여러 사용자가 동시에 로그인하는 웹서비스에서
스레드를 사용하지 않으면 한 명씩 순서대로 로그인 처리해야 하므로 느립니다.
하지만 스레드를 사용하면 동시에 여러 사람의 요청을 병렬로 처리할 수 있어 훨씬 빠릅니다.
Runnable
은 Java의 인터페이스로, 스레드에서 실행할 작업을 정의할 때 사용합니다.run()
이 있습니다. 이 메서드 안에 스레드가 실행할 코드를 작성합니다.Thread
클래스는 Runnable
객체를 인자로 받는 생성자를 제공합니다.public class Main {
public static void main(String[] args) {
System.out.println("main thread start");
Runnable run = new Runnable() {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.print(i + "\t");
try {
Thread.sleep(1000); // 1초 대기
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
Thread forThread = new Thread(run);
forThread.start();
System.out.println("main thread end");
}
}
여러 스레드가 하나의 자원(변수, 객체 등)을 동시에 접근할 때 문제가 발생할 수 있습니다.
🧠 예시
두 사람이 동시에 하나의 문서를 수정하면 내용이 꼬임
이런 걸 동시성 문제(concurrency issue)라고 합니다.
synchronized
synchronized
키워드를 사용하면
한 스레드가 자원을 사용하는 동안 다른 스레드는 기다렸다가 순차적으로 처리합니다.
다음 예제는 공유 객체 Prt
를 사용하는 두 개의 스레드 간 동시성 문제를 보여줍니다.
public class Prt {
public void printChar(char charValue) {
for (int i = 0; i < 10; i++) {
System.out.print(charValue);
}
System.out.println();
}
}
public class PrtThread implements Runnable {
private Prt moniter;
private char charValue;
public PrtThread(Prt moniter, char charValue) {
this.moniter = moniter;
this.charValue = charValue;
}
@Override
public void run() {
synchronized (moniter) {
for (int i = 0; i < 10; i++) {
moniter.printChar(charValue);
}
}
}
}
public class PrtThreadApp {
public static void main(String[] args) {
Prt prt = new Prt();
PrtThread charA = new PrtThread(prt, 'A');
Thread thread01 = new Thread(charA);
thread01.start();
PrtThread charB = new PrtThread(prt, 'B');
Thread thread02 = new Thread(charB);
thread02.start();
}
}
thread01
과 thread02
는 동시에 prt.printChar()
메서드를 호출하려 합니다.synchronized
) 키워드가 없다면 두 스레드가 서로 충돌하여 출력 순서가 뒤섞입니다.synchronized (printer)
블록으로 감싸줌으로써 한 스레드씩 차례대로 접근하도록 합니다.synchronized
가 없다면 출력이 ABABABA처럼 뒤섞일 수 있습니다.AAAAAAAAAA
BBBBBBBBBB