Java_21_스레드(Thread)

OngTK·2025년 8월 2일

Java

목록 보기
21/35

1. 스레드 Thread


1) 정의

  • 하나의 프로세스 내에서 실행되는 작업의 단위 ≒ 실행 흐름의 단위

2) 목적

  • 스레드를 통해 코드(명령어)를 읽어 CPU가 명령어를 처리하도록 함

3) 자바에서의 스레드

(1) main method

  • public static void main( String[] args ){} >> main thread를 내장하고 있음

4) 사용법

(1) main thread·method 선언

  • 자바 프로그램은 항상 main thread·method로부터 실행 흐름이 시작됨
public class Practice {
    public static void main(String[] args) {
        Toolkit toolkit = Toolkit.getDefaultToolkit(); // Java UI

        // [1] 싱글·단일 스레드
        System.out.println("[1] main thread가 읽어내는 코드");

        for (int i = 1; i <= 5; i++) {
            System.out.println("[1] main thread가 읽어내는 코드" + i);
        }

        for (int i = 1; i <= 5; i++) {
//            System.out.println("[1] Beep sound");
            toolkit.beep(); // beep sound 출력 함수
            try {
                Thread.sleep(1000);             // Thread.sleep = milli sec 만큰 처리·Thread를 지연시킴
            } catch (InterruptedException e) {
                System.out.println("[예외발생] [1] " + e);
            }
        }
    } // main end
} // class end

2. 멀티스레드 Multi Thread


1) 정의

main 스레드 외 새로운 작업 스레드를 생성하여 동시 작업

2) 목적

  • 병렬 처리 = 동시에 여러 작업을 수행하기 위해

3) 사용처

  • Wep / App, 채팅 / 첨부파일 / JDBC, 동기화/비동기화 처리

4) 사용법

(1) 익명 구현체
(2) 구현체
(3) 상속
※ 상속은 클래스당 1번밖에 되지 않아서 사용성이 떨어짐

5) 주요 Class/Interface

(1) Thread Class

① .start()

  • run 추상 메소드를 실행하는 메소드

(2) Runnable Interface

① run(){} 추상 메소드

  • 작업 스레드가 실행되는 최초 시작점
// [2.2] 구현체 =====================================================
class 작업스레드1 implements Runnable {
    @Override
    public void run() {
        Toolkit toolkit = Toolkit.getDefaultToolkit();
        for (int i = 1; i <= 5; i++) {
            toolkit.beep();
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                System.out.println("[예외발생] [2.1.2] " + e);
            }
        }
    } // run end
} // class end

// [2.3] 상속 =====================================================
class 작업스레드2 extends Thread {
    Toolkit toolkit = Toolkit.getDefaultToolkit();

    public void run() {
        for (int i = 1; i <= 5; i++) {
            toolkit.beep();
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                System.out.println("[예외발생] [2.1.2] " + e);
            }
        }
    } // func end
    // Runnable 없이 run()에 바로 override 함
} // class end

public class Practice {
    public static void main(String[] args) {
        // [2] 멀티 스레드
        // [2.1] 익명 구현체 : 인터페이스 타입을 Class 없이 main Thread 안에서 직접 구현하는 것

        // [2.1.2] 소리 5번 코드
        // new 인터페이스Type(){ 구현 }
        Runnable runnable1 = new Runnable() {
            // Run 추상 매소드 구현
            public void run() {
                for (int i = 1; i <= 5; i++) {
                    toolkit.beep();
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        System.out.println("[예외발생] [2.1.2] " + e);
                    }
                }
            }
        }; // new Runnable() end

        // run 메소드를 구현한 > Runnable 인테페이스 > Thread 생성자에 대입
        Thread thread1 = new Thread(runnable1);
        thread1.start();

        // [2.1.1] 출력 5번 코드
        for (int i = 1; i <= 5; i++) {
            System.out.println("[1] main thread가 읽어내는 코드" + i);
            try {
                Thread.sleep(1000);
            } catch (Exception e) {
                System.out.println("[예외발생] [2.1.1] " + e);
            }
        }

        // [2.2] 구현체
        // [2.2.1] 구현체 스레드 (작업스레드1 구현체 class 참고하기!)
        작업스레드1 작업스레드1 = new 작업스레드1(); // 구현체
        Thread thread2 = new Thread(작업스레드1); // 구현체 '작업스레드1'을 Thread 타입의 thread2 변수에 대입
        thread2.start();                        // Thread 실행 함수 .start()

        // [2.2.2] 출력 5번
        for (int i = 1; i <= 5; i++) {
            System.out.println("[1] main thread가 읽어내는 코드" + i);
            try {
                Thread.sleep(1000);
            } catch (Exception e) {
                System.out.println("[예외발생] [2.1.1] " + e);
            }
        }

        // [2.3] 상속
        // [2.3.1] 상속class
        작업스레드2 thread3 = new 작업스레드2();
        thread3.start();


        // [2.3.2] 출력 5번
        for (int i = 1; i <= 5; i++) {
            System.out.println("[1] main thread가 읽어내는 코드" + i);
            try {
                Thread.sleep(1000);
            } catch (Exception e) {
                System.out.println("[예외발생] [2.1.1] " + e);
            }
        }
    }
}

3. 스레드풀


1) 정의

  • 미리 일정 개수의 스레드를 생성하고 필요에 따라 재사용하는 방법

2) 목적

  • 스레드의 재사용

3) 효과

  • 자원 효율성, 과부하 방지 etc

4) 구조

  • 작업 요청 [ 큐 ] 자료구조를 배치하여 순서대로 스레드풀에서 대기중인 스레드에게 작업 배정

    ※ 큐
    : 자료의 데이터들을 요청 순서대로 처리하는 방법

5) 사용처

(1) 톰켓 (자바웹클래스)
(2) JDBC
(3) 업로드/다운로드
(4) 채팅

6) 사용법

(1) 작업 스레드 배정

public class Practice {
    public static void main(String[] args) {
        // (1) 작업 스레드 배정
        // Executor.newFixedThreadPool( 스레드풀에 저장할 스레드 수 );
        ExecutorService executorService = Executors.newFixedThreadPool(3);

        // (2) 반복문을 이용하여 각 스레드를 생성
        for(int i = 0 ; i < 3 ; i++){
            String name = "Thread" + i ;

            // (3) 스레드 생성 - 익명 구현체
            Runnable runnable = new Runnable(){
                @Override
                public void run() {
                    try{
                        Thread.sleep(2000);
                    } catch (Exception e ) {System.out.println("[예외발생] + e ");}
                    System.out.println("Task Thread ? ; "+ name);
                } //func end

            }; // 익명구현체 end

            // (4) 생성된 스레드를 스레드풀에 삽입
            executorService.submit( runnable );
        } // for end

        // (5) 스레드풀 종료
        executorService.shutdown();
    } //main end
} // class end
profile
2025.05.~K디지털_풀스택 수업 수강중

0개의 댓글