
하나의 프로그램 내에서 각기 다른 실행부를 둘 수 있는 것
멀티태스킹을 위해 사용
같은 메모리 공간(method, heap 등)을 공유하면서
stack 영역은 각 스레드마다 따로 존재
➡ 각 스레드가 완전히 독립적으로 자기만의 실행 공간을 가진다는 뜻
1. Thread 클래스를 상속하고 run() 메서드를 오버라이딩
↓
2. new로 객체 생성 (new ThreadA())
↓
3. start() 호출
→ JVM이 해당 스레드를 Runnable 상태로 등록 (Ready Queue)
↓
4. OS가 스케줄링하여 CPU를 할당
→ Running 상태로 진입
↓
5. run() 메서드 실행 시작
↓
6. run() 종료 → Terminated 상태
start()
start()는run()을 직접 실행하는 게 아니라,
JVM에게 “얘를 새로운 스레드로 실행해줘”라고 요청하는 것그래서
run()을 직접 호출하면 그냥 일반 메서드 실행이고, 스레드가 만들어지는 게 아님

스윙의 UI컴포넌트 중 진행률을 표현하는 컴포넌트인 JProgressBar를 사용해보자
import java.awt.*;
import javax.swing.*;
public class ProgressApp extends JFrame {
JProgressBar[] bar = new JProgressBar[3];
JButton bt;
public ProgressApp() {
setLayout(new FlowLayout());
for (int i = 0; i < bar.length; i++) {
bar[i] = new JProgressBar();
bar[i].setPreferredSize(new Dimension(750, 45));
add(bar[i]);
}
bt = new JButton("진행");
add(bt);
bt.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
//Thread 생성
new ProgressThread(bar[0], 5).start();
new ProgressThread(bar[1], 2).start();
new ProgressThread(bar[2], 8).start();
}
});
setSize(800, 600);
setVisible(true);
setDefaultCloseOperation(EXIT_ON_CLOSE);
}
public static void main(String[] args) {
new ProgressApp();
}
}
import javax.swing.JProgressBar;
public class ProgressThread extends Thread {
JProgressBar bar;
int n;
int velX;
public ProgressThread(JProgressBar bar, int velX) {
this.bar = bar;
this.velX = velX;
}
@Override
public void run() {
while (true) {
try {
Thread.sleep(10);
// if (n > 100) break;
// if를 앞에 둘 거면 n > 100으로 해야 100까지 보여주고 멈출 수 있음
n += velX; // 먼저 증가
bar.setValue(n); // 증가된 값 반영
if (n >= 100) break; // 100을 넘으면 루프 종료 (종료 조건)
} catch (InterruptedException e) {
e.printStackTrace();
break;
}
}
}
}
막대 움직이는 스레드 → 재사용 가능하게 .java 파일로 따로 분리
JProgressBar 하나당 스레드 하나씩 생성해야 함
✅ 스레드는 각각 독립 실행, 클래스는 공통 사용