오늘의하루

[Java] Process & Thread (프로세스와 스레드) 알아보기 본문

JAVA

[Java] Process & Thread (프로세스와 스레드) 알아보기

오늘의하루_master 2022. 9. 5. 15:32

프로세스와 스레드 구분하기

모든 프로세스는 최소한 1개 이상의 스레드를 가지고 있다.

프로세스(공장) : 실행 중인 프로그램, 자원(resources)과 스레드로 구성되어있다.

  • 자원은 메모리, cpu.. 등등
  • 메모리에는 프로세스에 필요한 소스코드, static 멤버, heap(동적 메모리 영역), stack(지역변수, 매개변수, 반환 값 등 일시적인 데이터) 공간을 확보한다.
  • 프로세스 생성 시 PCB블록이 함께 생성된다.

스레드(일꾼) : 프로세서 내에서 실제 작업을 수행하는 것을 말한다.

  • 경량화된 프로세스 : 스레드는 프로세스의 소스코드, static멤버, heap을 공통된 자원으로 사용한다.
    • 스레드는 stack만 별도로 가지고 있다.
  • 싱글 스레드 : 자원 + 스레드 1
  • 멀티 스레드 : 자원 + 스레드 1 + 스레드 2 + 스레드 3... + 스레드 N
    • 실제 프로그램은 멀티 스레드로 만들어진다.

멀티 스레드의 장단점

장점

  • 시스템 자원을 보다 효율적으로 사용할 수 있다.
  • 사용자에 대한 응답성이 향상된다.
  • 작업이 분리되어 코드가 간결해진다.

단점

  • 동기화에 주의해야 한다.
  • 교착상태(dead-lock)가 발생하지 않도록 주의해야 한다.
    • 위 두 개의 단점은 각 스레드가 자원을 공유하다가 발생할 수 있는 문제이다.
  • 각 스레드가 효율적으로 고르게 실행될 수 있게 해야 한다.

스레드의 구현과 실행

스레드의 경우 상속(extends)과 구현(implements) 두 가지 방법이 있다.

  • Thread 클래스 상속으로 생성 및 사용
class Thread_extends extends Thread{
    public void run(){ // Thread 클래스의 run() 오버라이딩
        // 작업내용
    }
}

Thread_extends th1 = new Thread_extends(); // 스레드 생성
th1.start(); // 스레드 실행
  • Runnable 인터페이스로 구현 및 사용
class Thread_implements Runnable{
    public void run(){ // Runnable 인터페이스의 추상 메서드 run() 구현
        // 작업내용
    }
}

Runnable r = new Thread_implements();
Thread th2 = new Thread(r); // 스레드 생성
// Thread th2 = new Thread(new Thread_implements); // 위 두줄을 한줄로 작성하기
th2.start(); // 스레드 실행

스레드 실행 - start( )

스레드를 생성한 후에 start()를 호출해야 스레드가 작업을 시작한다.

ThreadEX1 th1 = new ThreadEx1();
ThreadEX1 th2 = new ThreadEx1();

th1.start();
th2.start();
  • start()는 시작이 아닌 시작한 준비를 완료한 것이다.
  • th1, th2 중에 어느 게 먼저 실행될지는 OS스케줄러가 결정한다.
  • th1이 먼저 start()했다고 먼저 사용된다는 보장은 없다.

start()

예제로 알아보기

class ThreadEx1 extends Thread{
    public void run(){
        for(int i = 0; i < 100; i++){
            System.out.print(0);
        }
    }
}

class ThreadEx2 implements Runnable{
    public void run(){
        for(int i = 0; i < 100; i++){
            System.out.print(1);
        }
    }
}

ThreadEx1 th1 = new ThreadEx1();
Thread th2 = new Thread(new ThreadEx2());
      
th1.start();
th2.start();
// 결과 (순서가 보장되지 않는다.)
// 00001011111001010001011100....

main 스레드

스레드의 종류는 사용자 스레드와 데몬 스레드(보조 스레드)가 있다.

  • 실행 중인 사용자 스레드가 없을 경우 프로그램이 종료된다.
  • 멀티 스레드의 경우 main 스레드가 종료돼도 다른 스레드가 있기 때문에 종료되지 않는다.

context switching

멀티 스레드에서 A에서 B로 넘어갈 때 소요되는 시간을 말한다.

context-switching

  • 멀티 스레드가 싱글 스레드 보다 최종 소요시간이 더 걸린다.

왜 시간이 더 걸리는 멀티 스레드를 사용할까?

이유는 소요시간이 조금 더 걸리더라도 여러 가지 작업을 동시에 진행할 수 있기 때문입니다.

  • 예를 들어 파일을 다운로드하면서 채팅을 하는 것이다.

스레드의 I/O 블로킹(blocking)

입력 출시 작업이 중단되는 것을 말한다.

// 싱글 스레드
String input = JOPtionPane.showInputDialog("값을 입력하세요.");
System.out.println("입력하신 값은 " + input + "입니다.");

for (int i = 10; i > 0; i--){
    System.out.println(i);
    try{
        Thread.sleep(100); // 1초 지연
    }catch(Exception e){}
}
// 결과
// 입력하신 값은 1 입니다.
// 10
// 9
// 8 ...
  • 이때 input을 입력하지 않으면 작업 중단(I/O 블로킹)이 된다.
  • 입력이 완료되면 그때부터 아래 있는 코드들이 실행된다.

I/O 블로킹을 해결하기 위해 멀티 스레드로 만들기

class ThreadM extends Thread{
     public void run(){
         for(int i = 10; i > 0; i--){
             System.out.println(i);
             try{
                 sleep(1000);
             }catch(Exception e){}
         }
     }
}

ThreadM th1 = new ThreadM();
th1.start();

String input = JOptionPane.showInputDialog("값을 입력하세요.");
System.out.println("입력하신 값은 " + input + "입니다.");
  • 카운트 다운과 입력창이 같이 실행된다.
  • 입력하지 않아도 카운트 다운은 된다.
Comments