안녕하세요 요즘 java 공부가 너무 재밌어서 꾸준히 공부하고 있는데 벌써 이 책도 절반이상을 공부했더라고요! 얼른 마무리 짓고 더 많은 공부를 하려고 노력중입니돳!!
 

아자아자 화이팅!!

 
 
오늘은 java에서 중요한 멀티 스레드를 공부해볼건데 드디어 멀티라는 개념이나오네요(감격!!ㅜㅜ)이번에는 중요한 내용이 많아서 두개로 나눠서 진행해보려고 합니다.!! 그럼 신나게 노래들으면서 시작해볼게요!

 
 
 오늘은 쌈$뽕#한! 노래로 신나게 공부합시다!!

ZICO - SPOT! (스퐛 스퐛 슾퐛~~~)

 
 
 

✅ 00. 스레드(Thread)
 멀티 스레드란(Multi Thread)?
운영체제는 실행 중인 프로그램을 프로세스(process)에서 관리합니다. 멀티 태스킹(multi tasking)은 두 가지 이상의 작업을 동시에 처리하는 것을 말하는데, 이때 운영체제는 멀티 프로세스를 생성해서 처리합니다. 
 

출처 - https://webcoding-start.tistory.com/62

 
하나의 프로세스가 두 가지 이상의 작업을 처리할 수 있는 이유는 멀티 스레드(Multi Thread)가 있기 때문입니다. 스레드는 코드의 실행 흐름을 말하는데, 프로세스 내에 스레드가 두 개라면 두 개의 코드실행 흐름이 생긴다는 의미입니다.
 
※ 멀티 스레드는 데이터를 분할해서 병렬로 처리하는 곳에서 사용하기도 하고, 안드로이드 앱에서 네트워크 통신을 하기 위해 사용하기도 합니다. 또한 다수의 클라이언트 요청을 처리하는 서버를 개발할때에도 사용됩니다. 
 

✅ 01. 메인 스레드(main Thread)
 메인 스레드란?
모든 자바 프로그램은 메인 스레드가 main() 메소드를 실행하면서 시작됩니다. 메인 스레드는 main() 메소드의 첫 코드부터 순차적으로 실행하고, main() 메소드의 마지막 코드를 실행하거나 return문을 만나면 실행을 종료합니다.

public static void main(String[] args){
    // 코드의 실행 흐름 -> 스레드
    String data = null;
    if(...){

    }
    while(...){

    }
    System.out.println("...");
}

메인 스레드는 필요에 따라 추가 작업 스레드들을 만들어서 실행시킬 수 있습니다. 아래에 그림을 보면 메인 스레드가 작업 스레드1을 생성하고 실행시킨 다음, 곧이어 작업 스레드2를 생성하고 실행시키는 것을 볼 수 있습니다.
 

출처 - https://velog.io/@mmy789/Java-%EB%A9%80%ED%8B%B0-%EC%8A%A4%EB%A0%88%EB%93%9C-1

 
싱글 스레드는 메인 스레드가 종료되면 프로세스도 종료되지만 멀티 스레드는 실행중인 스레드가 하나라도 있다면 프로세스는 종료되지 않습니다.
 
※ 메인 스레드가 작업 스레드보다 먼저 종료되더라도 작업 스레드가 계속 실행 중이라면 프로세스는 종료되지 않습니다.
 

오케이~~ 이해했다(물어보지는 말아줘~)

 
 

다음예제를 보면서 스레드를 활용한것을 볼수있습니다. 우선 beepThread라는 객체를 생성해서 0.5초에 한번씩 비프음이 나올 수 있게 코드를 만들었습니다. 
 

그 다음으로 아래에 printThread라는 객체를 생성했고 위에 코드와 마찬가지로 Runnable 객체를 Override해서 가독성과 정확성을 높였습니다. 그로 인해 동일하게 0.5에 한번씩 "띵" 이라는 문구가 출력되게 구현했습니다.

(비프음)
띵
(0.5초 후)
(비프음)
띵
(0.5초 후)
(비프음)
띵
...

결과적으로, 코드를 실행하게 되면 다음과 같이 동시에 두가지 작업을 할 수 있습니다. (👀👀신기신기)

package Muti;

import java.awt.Toolkit;

public class Mutithread {
    public static void main(String[] args) {
        Thread beepThread = new Thread(new Runnable() {
            @Override
            public void run() {
                Toolkit toolkit = Toolkit.getDefaultToolkit();
                for (int i = 0; i < 5; i++) {
                    toolkit.beep();
                    try {
                        Thread.sleep(500);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        });

        Thread printThread = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 5; i++) {
                    System.out.println("띵");
                    try {
                        Thread.sleep(500);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        });

        beepThread.start();
        printThread.start();
    }
}

 
 
✅ 02. 스레드 이름
 스레드 이름이란?
스레드는 자신의 이름을 가지고 있습니다. 메인 스레드는 'main'이라는 이름을 가지고 있고, 작업 스레드는 자동적으로 'Thread-n'이라는 이름을 가집니다. 다른 이름으로 설정하고 싶다면 Thread 클래스의 setName() 메소드를 사용하면 됩니다.

package Muti;

public class ThreadName {
    public static void main(String[] args) {
        Thread mainThread = Thread.currentThread();
        System.out.println(mainThread.getName() + " 실행");
    
        for(int i = 0; i < 3; i++) {
            Thread threadA = new Thread() {
                @Override
                public void run() {
                    System.out.println(getName() + " 실행");
                }
            };
            threadA.start();
        }
        
        Thread chatThread = new Thread() {
            @Override
            public void run() {
                System.out.println(getName() + " 실행");
            }
        };
        chatThread.setName("chat-thread");
        chatThread.start();
    }
}

다음 예제를 보면 스레드 이름은 디버깅할 때 어떤 스레드가 작업을 하는지 조사할 목적으로 주로 사용됩니다. 현재 코드를 어떤 스레드가 실행하고 있는지 확인하려면 정적 메소드인 currentThread()로 스레드 객체의 참조를 얻은 다음 getName() 메소드로 이름을 출력합니다.
 
출력값을 보게되면 알수있듯이, 현재 실행 중인 스레드의 참조를 얻어 이름을 콘솔에 출력되고, 작업 스레드의 이름을 setName() 메소드로 수정해서 chat-thread로 바뀐것을 알 수 있습니다.
 
 
✅ 02. 스레드 상태
 스레드 상태란?
스레드 객체를 생성(NEW)하고, start() 메소드를 호출하면 바로 스레드가 실행되는 것이 아니라 실행 대기 상태(RUNNABLE)가 됩니다. 실행 대기상태란 실행을 기다리고 있는 상태를 말합니다. 실행 대기하는 스레드는 CPU 스케쥴링에 따라 CPU를 점유하고 run() 메소드를 실행합니다. 이때를 실행 상태(RUNNING)라고 합니다.
 

출처 - https://m.blog.naver.com/qbxlvnf11/220921178603

 
 
이렇게 스레드는 실행 대기 상태와 실행 상태를 번갈아 가면서 자신의 run() 메소드를 조금씩 실행합니다. 실행 상태에서 더 이상 실행할 코드가 없으면, 스레드의 실행은 멈추게 됩니다. 이때 상태를 종료 상태(TERMINATED) 라고 합니다.
 
 

출처 - https://velog.io/@sa1341/%EB%A9%80%ED%8B%B0-%EC%8A%A4%EB%A0%88%EB%93%9C%EC%9D%98-%EC%83%81%ED%83%9C-%EC%A0%9C%EC%96%B4

 
실행 상태에서 일시 정지 상태로 가기도 하는데, 일시 정지 상태는 스레드가 실행할 수 없는 상태를 말합니다. 스레드가 다시 실행 상태로 가기 위해서는 일시 정지 상태에서 실행 대기 상태로 가야합니다.
 
 
다른 스레드의 종료를 기다림

다음 예제는 SumThread가 계산 작업을 모두 마칠 때가지 메인 스레드가 일시 정지 상태에 있다가 SumThread가 최종 계산된 결과값을 산출하고 종료하면 메인 스레드가 결과값을 받아 출력합니다.
 

 
SumThread가 JoinExample의 join() 메소드를 호출하면 SumThread는 JoinExample가 종료할 때까지 일시 정지 상태가 됩니다. JoinExample의 try-catch가 종료되면 일시정지가 풀려 다음 코드를 실행합니다.
 
 
다른 스레드에게 실행 양보 
스레드가 처리하는 작업은 반복적인 실행을 위해 for 문이나 while 문을 포함하는 경우가 많은데, 가끔 반복문이 무의미한 반복을 하는 경우가 있습니다. 이때는 다른 스레드에게 실행을 양보하고 자신은 실행 대기 상태로 가는 것이 프로그램 성능에 도움이 됩니다. 

출처 - https://velog.io/@sa1341/%EB%A9%80%ED%8B%B0-%EC%8A%A4%EB%A0%88%EB%93%9C%EC%9D%98-%EC%83%81%ED%83%9C-%EC%A0%9C%EC%96%B4

 
 

이번 예제는 무의미한 반복을 하지 않고 다른 스레드에게 실행을 양보하도록 한것입니다.

 처음 5초동안 threadA와 threadB가 번갈아 가며 실행하다가 5초뒤에 메인 스레드가 threadA의 work 필드를 false로 변경함으로써 threadA가 yield() 메소드를 호출합니다. 따라서 threadB가 더 ㅁ낳은 실행 기회를 얻게 됩니다. 그리고 10초뒤에 threadA의 work 필드를 true로 변경해 다시 번갈아 가며 실행되도록 합니다. 

 
 
 
 
 

으으으으윽...!!

 
(우선 스레드는 내용이 길어져서 다음편으로 이어서 하겠습니다.!!!)

'Java' 카테고리의 다른 글

12. Java - 제네릭(Generic)  (0) 2024.07.02
11. Java - 예외처리  (1) 2024.06.25
10. Java - 상속  (0) 2024.05.12
09. Java - 클래스(3)_인스턴스/정적멤버  (1) 2024.05.10
08. Java - 클래스(2)_실습편  (0) 2024.05.10
2024. 7. 4. 15:06