[JAVA] 프로세스와 스레드: 개념, Java의 쓰레드 구현, I/O Blocking

2023. 9. 8. 18:00· JAVA
목차
  1. 💋 인트로
  2. 💋 개념
  3. 💋 멀티쓰레딩의 장단점
  4. 💋 Java의 Thread 구현
  5. ✔ 생성
  6. ✔ 실행: start()
  7. ✔ start() vs run()
  8. ✔ main 쓰레드
  9. 💋 싱글 쓰레드 VS 멀티 쓰레드
  10. ✔ 싱글 쓰레드
  11. ✔ 멀티 쓰레드
  12. 💋 I/O Blocking
  13. ✔ 싱글 쓰레드
  14. ✔ 멀티 쓰레드
  15. 💋 참고자료
반응형

💋 인트로

과거의 컴퓨터는 한 번에 하나의 작업만 가능했다.

사진을 다운로드 받는 작업, 마우스나 키보드로부터 입력을 받는 작업, 브라우저로 사이트를 돌아다니는 작업을 동시에 할 수 없었다.

이후 컴퓨터는 동시에 여러 개의 작업을 하는 멀티태스킹이 가능해졌다.

배경에 있는 프로세스, 쓰레드에 대해 알아보자.

 

💋 개념

  • 프로세스
    • 실행중인 프로그램
    • 프로그램을 실행하면 OS로부터 자원(메모리)을 할당받아 프로세스가 됨.
  • 쓰레드
    • 프로세스의 자원을 이용해 실제로 작업을 수행하는 것
  • 프로세스의 구성
    • 자원(데이터, 메모리) + 쓰레드
      • 모든 프로세스는 1개 이상의 쓰레드가 존재
      • 2개 이상의 쓰레드를 가진 프로세스는 ‘멀티 쓰레드 프로세스’

 

💋 멀티쓰레딩의 장단점

  • 장점
    • CPU 사용률 향상
    • 자원을 효율적으로 사용할 수 있음.
      • 하나의 작업을 하는 동안에도 다른 작업을 수행할 수 있음.
    • 사용자에 대한 응답성 향상
      • 하나의 작업을 하는 동안에도 다른 작업에 응답할 수 있음.
    • 작업이 분리되어 코드가 간결해짐.
  • 단점
    • 여러 쓰레드가 같은 프로세스 내에서 자원을 공유하면서 작업함.
      • 동기화(synchronization) 문제 발생 가능
      • 교착상태(deadlock) 문제 발생 가능
        • 두 쓰레드가 자원을 점유한 상태에서 서로 상대편이 점유한 자원을 사용하려고 기다리느라 진행이 멈춰있는 상태
    • 단순히 시간만 비교해 보았을 때, 싱글 쓰레드에 비해 오래 걸림.
      • context switching에 시간이 걸리기 때문
      • 전환을 위해서는 현재 진행중인 작업의 상태의 정보를 저장하고 읽어오는 데에 시간이 걸림.

💋 Java의 Thread 구현

✔ 생성

  1. Thread 클래스를 상속해서 구현
public class MyThread extends Thread {

    public static void main(String[] args) {
        MyThread thread = new MyThread();
        thread.run();
    }

    @Override
    public void run() {
        System.out.println("쓰레드 시작!");
    }
}
  1. Runnable 인터페이스를 구현
public class MyThread implements Runnable {

    public static void main(String[] args) {
        Runnable runnable = new MyThread();
        Thread thread = new Thread(runnable); // 생성자 Thread(Runnable runnable)
        thread.run();
    }

    @Override
    public void run() {
        System.out.println("쓰레드 시작!");
    }
}

✔ 실행: start()

public static void main(String[] args) {
        Runnable runnable = new MyThread();
        Thread thread = new Thread(runnable);

        thread.start();
    }
  • start()를 호출해 쓰레드 실행
    • 실행 대기 상태에 있다가, 자신의 차례가 되면 실행됨.
    • 실행 순서는 OS 스케줄러의 스케줄에 따름.
  • 한 번 실행이 종료된 쓰레드는 다시 실행할 수 없음.
    • 하나의 쓰레드에 두 번 이상 start() 를 호출하면, IllegalThreadStateException 발생

✔ start() vs run()

  • start()
    • 쓰레드를 실행함.
    • 쓰레드가 작업을 하는데 필요한 호출 스택(call stack)을 생성한 후에 run()을 호출해서, 생성된 호출스택에 run()이 첫번째로 올라가게 함.
  • run()
    • 단순히, 클래스에 선언된 메서드를 호출함.

 

  1. main 메서드에서 쓰레드의 start() 호출
  2. start()가 새로운 쓰레드를 생성 + 쓰레드가 작업할 호출 스택 생성
  3. 새로운 호출스택에 run() 호출되어, 쓰레드가 독립된 공간에서 작업 수행
  4. 호출 스택이 2개이므로 OS 스케줄러의 스케줄에 따라 번갈아가면서 실행

✔ main 쓰레드

  • main 메서드의 작업을 실행하는 것도 쓰레드임.
  • 프로그램의 실행을 위해 수행하는 쓰레드가 적어도 1개 있어야 함.
    • 해당 쓰레드가 main 메서드를 호출해, 작업이 수행되도록 함.

💋 싱글 쓰레드 VS 멀티 쓰레드

✔ 싱글 쓰레드

public class SingleThread {

    public static void main(String[] args) {
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < 300; i++) {
            System.out.printf("%s", new String("?"));
        }
        long time1 = System.currentTimeMillis() - startTime;
        System.out.println("time1 = " + time1);

        for (int i = 0; i < 300; i++) {
            System.out.printf("%s", new String("!"));
        }

        long time2 = System.currentTimeMillis() - startTime;
        System.out.println("time2 = " + time2);
    }
}

결과

> Task :tomcat:SingleThread.main()
????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????time1 = 26
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!time2 = 37
  • 두 개의 쓰레드가 작업을 하나씩 차례대로 수행함.

✔ 멀티 쓰레드

public class MultiThread {

    static long startTime = 0;

    public static void main(String[] args) {
        Runnable runnable = new MyThread();
        Thread thread = new Thread(runnable);
        thread.start();

        startTime = System.currentTimeMillis();

        for (int i = 0; i < 300; i++) {
            System.out.printf("%s", new String("!"));
        }

        long time1 = System.currentTimeMillis() - MultiThread.startTime;
        System.out.println("time1 = " + time1);
    }

    static class MyThread implements Runnable {

        @Override
        public void run() {
            for (int i = 0; i < 300; i++) {
                System.out.printf("%s", new String("?"));
            }

            long time2 = System.currentTimeMillis() - MultiThread.startTime;
            System.out.println("time2 = " + time2);
        }
    }
}

결과

> Task :tomcat:MultiThread.main()
!!!!!!!????????????????????????????????????????????????????!?????????????!!!!!!!!!!!!!!!!!!!!!!!!!???!!!!!!!!!!!!!!!!!!!!!!!!!!??????????????????????????????!!!!!!!!!!!!!!!!!!!!!!????????????????????????????????????????????????????????????????????????????????????????????????????????!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!????!!!??????????????????????????????????????????????????!!!?????????????????????????????????!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!???????????!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!time2 = 32
  • 두 작업이 아주 짧은 시간 동안 번갈아가면서 실행되고, 거의 도잇에 완료됨.

💋 I/O Blocking

  • 쓰레드가 입출력 처리를 위해 기다리는 것
  • 사용자로부터 입력받는 작업과 화면에 출력하는 작업을 하나의 쓰레드로 처리한다면, 해당 쓰레드는 사용자가 입력을 마칠 때까지 아무런 일도 하지 못하게 되므로, 멀티 쓰레드로 처리하는 것이 효율적임.

✔ 싱글 쓰레드

public class ThreadIOBlocking {
    public static void main(String[] args) throws InterruptedException {
        // 사용자로부터 입력받기
        String input = JOptionPane.showInputDialog("값을 입력해 주세요.");
        System.out.println("input = " + input);

        // 화면에 숫자를 출력하기
        for (int i = 0; i < 10; i++) {
            System.out.println("i = " + i);
            Thread.sleep(1000);
        }
    }
}
  • 사용자가 값을 입력할 때까지 화면에 숫자가 출력되지 않음.

 

✔ 멀티 쓰레드

public class MultiThread {

    public static void main(String[] args) {
        Runnable runnable = new MyThread();
        Thread thread = new Thread(runnable);
        thread.start();

        // 사용자로부터 입력받기
        String input = JOptionPane.showInputDialog("값을 입력해 주세요.");
        System.out.println("input = " + input);
    }

    static class MyThread implements Runnable {

        @Override
        public void run() {
            // 화면에 숫자를 출력하기
            for (int i = 0; i < 10; i++) {
                System.out.println("i = " + i);
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException ignored) {
                }
            }
        }
    }
}
  • 사용자가 입력을 마치지 않아도 화면에 숫자가 출력되기 시작함.

 

 

💋 참고자료

  • https://velog.io/@underlier12/OS-20-쓰레드-개념
  • 자바의 정석 2편
반응형
저작자표시 비영리 변경금지 (새창열림)

'JAVA' 카테고리의 다른 글

[JAVA] 멀티 쓰레드의 동기화(synchronization): 메서드, 메서드 내 블록에 synchronized 키워드를 붙이자!  (0) 2023.09.10
[JAVA] 쓰레드 풀(Thread Pool): 개념, 장점, 사용 방법, 코드 예시 (feat. Baeldung)  (1) 2023.09.09
[JAVA] 좋은 객체 지향 설계의 5가지 원칙 (SOLID)  (0) 2023.05.01
[Spring] Spring Core(3): IoC Container의 개념, 생명 주기  (2) 2023.04.23
[JAVA] 좋은 코드가 되려면 꼭 지켜야 할 기본적인 컨벤션  (0) 2023.04.13
  1. 💋 인트로
  2. 💋 개념
  3. 💋 멀티쓰레딩의 장단점
  4. 💋 Java의 Thread 구현
  5. ✔ 생성
  6. ✔ 실행: start()
  7. ✔ start() vs run()
  8. ✔ main 쓰레드
  9. 💋 싱글 쓰레드 VS 멀티 쓰레드
  10. ✔ 싱글 쓰레드
  11. ✔ 멀티 쓰레드
  12. 💋 I/O Blocking
  13. ✔ 싱글 쓰레드
  14. ✔ 멀티 쓰레드
  15. 💋 참고자료
'JAVA' 카테고리의 다른 글
  • [JAVA] 멀티 쓰레드의 동기화(synchronization): 메서드, 메서드 내 블록에 synchronized 키워드를 붙이자!
  • [JAVA] 쓰레드 풀(Thread Pool): 개념, 장점, 사용 방법, 코드 예시 (feat. Baeldung)
  • [JAVA] 좋은 객체 지향 설계의 5가지 원칙 (SOLID)
  • [Spring] Spring Core(3): IoC Container의 개념, 생명 주기
깃짱
깃짱
연새데학교 컴퓨터과학과 & 우아한테크코스 5기 백엔드 스타라이토 깃짱
반응형
깃짱
깃짱코딩
깃짱
전체
오늘
어제
  • 분류 전체보기
    • About. 깃짱
    • Weekly Momentum
      • 2024
    • PROJECT
      • AIGOYA LABS
      • Stamp Crush
      • Sunny Braille
    • 우아한테크코스5기
    • 회고+후기
    • Computer Science
      • Operating System
      • Computer Architecture
      • Network
      • Data Structure
      • Database
      • Algorithm
      • Automata
      • Data Privacy
      • Graphics
      • ETC
    • WEB
      • HTTP
      • Application
    • C, C++
    • JAVA
    • Spring
      • JPA
      • MVC
    • AI
    • MySQL
    • PostgreSQL
    • DevOps
      • AWS
      • 대규모 시스템 설계
    • frontend
      • HTML+CSS
    • NextJS
    • TEST
    • Industrial Engineering
    • Soft Skill
    • TIL
      • 2023
      • 2024
    • Linux
    • Git
    • IntelliJ
    • ETC
      • 日本語

블로그 메뉴

  • 홈
  • 깃허브

인기 글

최근 글

태그

  • 람다와스트림
  • 상속과조합
  • 컴포지션
  • 우테코
  • 예외
  • 우아한테크코스5기
  • 상속
  • OOP
  • 조합
  • TDD
  • 레벨로그
  • 함수형프로그래밍
  • 스트림
  • 우테코5기
  • lamda
  • Composition
  • 람다
  • Stream
  • 우아한테크코스
  • Java
hELLO · Designed By 정상우.v4.2.0
깃짱
[JAVA] 프로세스와 스레드: 개념, Java의 쓰레드 구현, I/O Blocking
상단으로

티스토리툴바

개인정보

  • 티스토리 홈
  • 포럼
  • 로그인

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.