
스레드를 알기 전에 알아가는 컴퓨터 상식
스레드와 프로세스
- 프로세스 → 하드 드라이브에서 메모리로 로드 된 프로그램을 프로세스라고 합니다. 프로세스를 관리하는 역할은 프로세서(CPU)가 맡습니다.
- 스레드 → 모든 프로세스는 최소 하나의 스레드를 가지고 있습니다. 스레드는 프로세스 내에서 실행되는 작업의 단위로, CPU가 이를 논리적으로 처리합니다. 이때 스레드는 자기 자신을 스레드로 처리 할 수 있다.
- 멀티스레딩 → CPU가 여러 스레드를 동시에 관리하면서, 여러 작업을 동시에 처리하는 것처럼 보이게 하는 기법입니다. 멀티스레딩은 프로그램의 속도를 빠르게 하는 것이 아니라, 여러 작업을 동시에 수행할 수 있게 해서 사용자 경험(UX)를 향상시킵니다.
메모리 관리
- 랜덤 액세스 메모리 (RAM) → 데이터를 임시로 저장하는 공간으로, CPU가 빠르게 데이터를 읽고 쓸 수 있습니다. 다이렉트로 이동한다.
- 스왑 → 메모리가 부족할 때, 현재 사용하지 않는 데이터를 하드 드라이브로 옮기고 (스왑 아웃), 필요한 데이터를 하드 드라이브에서 메모리로 불러오는 (스왑 인) 과정입니다.
- 가상 메모리 → 메모리가 부족할 때, 하드 드라이브의 일부 공간을 마치 추가적인 메모리인 것처럼 사용하는 기법입니다.
하드 드라이브
- 하드 드라이브에 저장하는 과정 → 메모리에서 하드 드라이브로 데이터를 이동시키는 과정을 커밋, 라이트, 또는 인풋이라고 합니다.
- 하드 드라이브에서 불러오는 과정 → 하드 드라이브에서 메모리로 데이터를 이동시키는 과정을 로드, 아웃풋, 또는 알로케이트라고 합니다.
- 시크 → 하드 드라이브의 읽기/쓰기 헤드가 데이터를 찾아가는 과정을 말합니다.
I/O와 웨이트 시간
- I/O(Input/Output) → 메모리와 하드 드라이브 사이에서 데이터가 오고 가는 모든 과정을 I/O라고 합니다. I/O는 CPU 처리 시간에 비해 상대적으로 많은 시간이 소요됩니다.
- 웨이트 시간 → CPU가 I/O 또는 다른 프로세스의 종료 등을 기다리는 시간을 말합니다.
추가적으로 알면 좋을 내용
- 컨텍스트 스위칭 → CPU가 여러 프로세스 또는 스레드를 돌아가면서 처리하기 위해, 현재 상태를 저장하고 다음 작업의 상태를 불러오는 과정을 말합니다.
- 라운드 로빈 스케줄링 → CPU의 시간을 각 프로세스에게 동일하게 할당하여, 모든 프로세스가 공평하게 CPU 시간을 사용하도록 하는 스케줄링 알고리즘입니다.
- 스레드의 생명 주기 → 스레드는 '생성', '실행 가능', '실행 중', '대기', '종료' 등의 상태를 가지며, 이러한 상태들은 스케줄러에 의해 관리됩니다. 스레드가 가지는 독립적인 스택에는 스레드가 수행하는 함수의 호출 정보와 지역 변수 등이 저장됩니다.
- 콜백 → 이벤트가 발생했을 때 시스템이 자동으로 호출하는 함수나 메소드를 말한다.
스레드(Thread)
- 작업을 진행하는 것을 “스레드”라 한다.
- 스레드는 실이라는 의미로, “하나의 실행 흐름(thread of execution)”을 의미한다.
- 스레드가 모여 있는 것을 “멀티 스레딩(multi-threading)”이라 한다.
- 자바는 스레드가 하나라도 살아있으면 종료되지 않는다.
- 메인 스레드는 가장 먼저 종료가 되는데, 종료되고 남아있는 서브 스레드들이 동시 실행되는데 이를 “컨텍스트 스위칭”이라 한다.
CPU가 풀파워로 돌면 다른 곳에서 이벤트가 발생 할 수 없다.
→ 이때 풀파워의 틈을 만드는게 “sleep”이다.
→ 이 틈에 움직이는 것을 “컨텍스트 스위칭”이라 한다.
- 동기식 실행과 비동기식 실행 → 스레드는 동기식과 비동기식 둘 다 처리가 가능하다.
- 작업을 순차적으로 진행하는 실행이다.
- 여러 작업을 동시에 진행하는 실행이다.
동기식 실행
비동기식 실행
동기적의 뜻!
데이터의 관점에서는 “데이터의 일관성(동일성)”을 뜻하고,
프로그래밍 관점에서는 ”일의 순서가 있다”를 뜻한다.
- 자바에서 스레드를 생성하여 작업하는 방법은 총 2가지가 있다. → Thread 클래스를 상속하는 방법 / Runnable 인터페이스를 구현하는 방법
- 스레드는 람다식을 이용하여 작성도 가능하다.
스레드 코드 설명
- 스레드 기본 코드와 sleep을 사용한 코드 → 비동기식의 형태로 출력이 된다.
package ex16.example1;
public class ThreadEx01 {
public static void sub1() {
for (int i = 1; i <= 5; i++) {
try {
System.out.println("start1 thread : " + i);
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
public static void sub2() {
for (int i = 1; i <= 5; i++) {
try {
System.out.println("start2 thread : " + i);
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
// main thread
public static void main(String[] args) {
Thread t1 = new Thread(() -> {
sub1();
});
t1.start();
// 실을 만드는 것
Thread t2 = new Thread(() -> {
sub2();
});
t2.start(); // 실을 시작하는것
} // main 스레드 종료
}
출력 결과

- Runnable을 사용한 코드 → 2개의 스레드가 실행되면서 스레드의 출력이 서로 섞여서 나온다.
package ex16;
class MyRunnable implements Runnable {
String myName;
public MyRunnable(String name) {
this.myName = name;
}
public void run() {
for (int i = 0; i <= 10; i++) {
System.out.println(myName + i + " ");
}
}
}
public class TestThread {
public static void main(String[] args) {
Thread t1 = new Thread(new MyRunnable("A"));
Thread t2 = new Thread(new MyRunnable("B"));
t1.start();
t2.start();
}
}
출력 결과

- 람다식을 활용한 코드
package ex16;
public class LambdaTest {
public static void main(String[] args) {
Runnable task = () -> {
for (int i = 0; i <= 10; i++) {
System.out.println(i + " ");
}
};
new Thread(task).start();
}
}
출력 결과

- 스레드를 상속받아 JFrame과 같이 사용한 코드 → 직접 코드를 출력해보면 더욱 쉽게 이해가 되는 코드이다.
package ex16;
import javax.swing.*;
import java.awt.*;
public class CountDownTest extends JFrame {
private JLabel label;
class MyThread extends Thread {
public void run() {
for (int i = 0; i <= 10; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
label.setText(i + "");
}
}
}
public CountDownTest() {
setTitle("카운트다운");
setSize(400, 150);
label = new JLabel("Start");
label.setFont(new Font("Serif", Font.BOLD, 100));
add(label);
setVisible(true);
new MyThread().start();
}
public static void main(String[] args) {
CountDownTest t = new CountDownTest();
}
}
Share article