스레드

InSeok·2022년 7월 21일
0

TIL

목록 보기
16/51

목차


1.스레드
2.스레드 동기화
3.예외처리
4.JVM

배운 내용


스레드

  • 애플리케이션이 실행되면 운영체제가 메모리를 할당해주며 애플리케이션이 실행된다.

프로세스

  • 실행중인 애플리케이션
  • 데이터, 컴퓨터 자원, 스레드로 구성

스레드

  • 프로세스 내에서 실행되는 소스코드의 실행흐름
  • 데이터와 애플리케이션이 확보한 자원을 활용하여 소스 코드를 실행

**메인 스레드(Main thread)**

  • 자바 애플리케이션을 실행하면 가장 먼저 실행되는 메서드는 main메서드이며, 메인 스레드가 main 메서드를 실행시켜준다.

Untitled

**멀티 스레드(Multi-Thread)**

  • 하나의 프로세스는 여러 개의 스레드를 가질 수 있으며, 이를 멀티 스레드 프로세스라 한다.
  • 하나의 애플리케이션 내에서 여러 작업을 동시에 수행하는 멀티 태스킹을 구현하는 데에 핵심적인 역할

Untitled

**스레드의 생성과 실행**

문법

  • 클래스 내부에 스레드가 수행할 코드 작성하며, run() 메서드 내에 스레드가 처리할 작업을 작성
  • run()메서드는 Runnable 인터페이스와 Thread 클래스에 정의되어져 있다.

작업스레드를 생성&실행 방법

  1. Runnable 인터페이스를 구현한 객체에서 run()을 구현하여 스레드를 생성하고 실행하는 방법

    public class ThreadExample1 {
        public static void main(String[] args) {
    
            // Runnable 인터페이스를 구현한 객체 생성
            Runnable task1 = new ThreadTask1();
    
            // Runnable 구현 객체를 인자로 전달하면서 Thread 클래스를 인스턴스화하여 스레드를 생성
            Thread thread1 = new Thread(task1);
    
            // 위의 두 줄을 아래와 같이 한 줄로 축약 가능
            // Thread thread1 = new Thread(new ThreadTask1());
    
    				// start() 메서드를 통해 run()메서드 내부의 코드 실행
    				thread1.start();
    
    //반복문 추가
    				for (int i = 0; i < 100; i++) {
                System.out.print("@");
            }
    
        }
    }
    
    // Runnable 인터페이스를 구현하는 클래스
    class ThreadTask1 implements Runnable {
    
        // run() 메서드 바디에 스레드가 수행할 작업 내용 작성
        public void run() {
            for (int i = 0; i < 100; i++) {
                System.out.print("#");
            }
        }
    }
    
    // 익명 Runnable 구현 객체를 활용하여 스레드 생성
            Thread thread1 = new Thread(new Runnable() {
                public void run() {
                    for (int i = 0; i < 100; i++) {
                        System.out.print("#");
                    }
                }
            });
    
            thread1.start();
    
            for (int i = 0; i < 100; i++) {
                System.out.print("@");
            }
        }
    }
    
  2. Thread 클래스를 상속 받은 하위 클래스에서 run()을 구현하여 스레드를 생성하고 실행하는 방법

public class ThreadExample2 {
    public static void main(String[] args) {

// Thread 클래스를 상속받은 클래스를 인스턴스화하여 스레드를 생성
        Thread thread2 = new ThreadTask2();

// 작업 스레드를 실행시켜, run() 내부의 코드를 처리
thread2.start();

        // 반복문 추가
        for (int i = 0; i < 100; i++) {
            System.out.print("@");
}
    }
}

// Thread 클래스를 상속받는 클래스 작성
class ThreadTask2 extends Thread {
// run() 메서드 바디에 스레드가 수행할 작업 내용 작성
    public void run() {
				for (int i = 0; i < 100; i++) {
            System.out.print("#");
    }
}

스레드의 이름

  • 메인스레드는 “main”이라는 이름을 가지며, 그 외에 추가적으로 생성한 스레드는 기본적으로 “Thread-n”이라는 이름을 가집니다.

**스레드의 이름 조회하기**

  • 스레드의_참조값.getName()으로 조회

**스레드의 이름 설정하기**

  • 스레드의_참조값.setName()으로 설정

**스레드 인스턴스의 주소값 얻기**

  • 실행 중인 스레드의 주소값을 사용할때, Thread 클래스의 정적 메서드인 currentThread()
    를 사용
  • ex) Thread.currentThread().getName()

**스레드 동기화**

  • 두 스레드가 동일한 데이터를 공유하게 되면 문제가 발생할 수 있다.
  • Thread.sleep(1000);
    • 스레드를 일시 정지시키는 메서드
    • 어떤 스레드가 일시 정지되면, 대기열에서 기다리고 있던 다른 스레드가 실행
  • try { … } catch ( ~ ) { … }
    • 예외 처리에 사용되는 문법
    • try의 블록 내의 코드를 실행하다가 예외 또는 에러가 발생하면 catch문의 블럭에 해당하는 내용을 실행

**임계 영역(Critical section)**

  • 오로지 하나의 스레드만 코드를 실행할 수 있는 코드 영역
  • synchronized 키워드 사용

임계영역 설정

// 1. 메서드 전체를 임계 영역으로 지정
// 반환 타입 좌측에 synchronized 키워드를 작성
public synchronized boolean withdraw(int money) {
	    if (balance >= money) {
	        try { Thread.sleep(1000); } catch (Exception error) {}
	        balance -= money;

// 2. 특정한 영역을 임계 영역으로 지정
// synchronized 키워드와 함께 소괄호(()) 안에 해당 영역이 포함된 객체의 참조를 넣고, 중괄호({})로 블럭을 열어, 블럭 내에 코드를 작성

public boolean withdraw(int money) {
			synchronized (this) {
			    if (balance >= money) {
			        try { Thread.sleep(1000); } catch (Exception error) {}
			        balance -= money;

락(Lock)

  • 임계 영역을 포함하고 있는 객체에 접근할 수 있는 권한

**스레드의 상태와 실행 제어**

  • start()는 스레드를 실행시키는 메서드는 아니라, 실행대기 상태로 만들어주는 메서드다.
  • 실행대기 상태가 되면 운영체제가 적절한 때에 스레드 실행

**스레드 실행 제어 메서드**

**sleep(long milliSecond)**

  • **milliSecond 동안 스레드를 잠시 멈춘다.**
  • 실행 상태에서 일시 정지(TIMED_WAITING) 상태로 전환
  • static void sleep(long milliSecond)
  • Thread의 클래스 메서드
  • sleep()에의해 일시정지된 스레드가 실행대기 상태로 복귀하는경우
    1. 인자로 전달한 시간 만큼의 시간이 경과한 경우
    2. interrupt()를 호출한 경우
      1. interrupt()가 호출되면 기본적으로 예외가 발생하기 때문에 try … catch
        문을 사용해서 예외 처리를 해주어야 한다.

**interrupt()**

  • sleep(), wait(), join()에 의해 일시 정지 상태에 있는 스레드들을 실행 대기
    상태로 복귀시킨다.
  • 멈춰있는 스레드가 아닌 다른 스레드에서 멈춰 있는 스레드.interrupt()를 호출하면, 기존에 호출되어 스레드를 멈추게 했던 sleep(), wait(), join()메서드에서 예외가 발생되며, 그에 따라 일시 정지가 풀리게 된다.

**yield()**

  • 다른 스레드에게 실행을 양보
  • ex) 운영 체제의 스케줄러에 의해 3초를 할당 받은 스레드 A가 1초 동안 작업을 수행하다가 yield()를 호출하면 남은 실행 시간 2초는 다음 스레드에게 양보
  • static void yield()

**join()**

  • ****특정 스레드가 작업하는 동안에 자신을 일시 중지상태로 만드는 상태 제어 메서드
  • 인자만큼의 시간이 경과하거나, interrupt()가 호출되거나, join()호출 시 지정했던 다른 스레드가 모든 작업을 마치면 다시 실행 대기상태로 복귀
  • void join()
  • void join(long milliSecond)
  • sleep 과 join의 차이
    • sleep()은 Thread 클래스의 static메서드 Thread.sleep(1000);
    • join()은 특정 스레드에 대해 동작하는 인스턴스 메서드 thread1.join();

**wait(), notify() : 스레드간 협업에 사용**

  • 스레드A가 공유 객체에 자신의 작업을 완료 → 스레드B와 교대하기 위해 notify()를 호출 notify()가 호출되면 스레드B가 실행 대기상태가 되며, 곧 실행

    스레드A는 wait()을 호출하며 자기 자신을 일시 정지상태로 만든다.

 WorkObject sharedObject = new WorkObject();

        ThreadA threadA = new ThreadA(sharedObject);
        ThreadB threadB = new ThreadB(sharedObject);

        threadA.start();
        threadB.start();
    }
}

class WorkObject {
    public synchronized void methodA() {
        System.out.println("ThreadA의 methodA Working");
        notify();
        try { wait(); } catch(Exception e) {}
    }

    public synchronized void methodB() {
        System.out.println("ThreadB의 methodB Working");
        notify();
        try { wait(); } catch(Exception e) {}
    }
}

class ThreadA extends Thread {
    private WorkObject workObject;

    public ThreadA(WorkObject workObject) {
        this.workObject = workObject;
    }

    public void run() {
        for(int i = 0; i < 10; i++) {
            workObject.methodA();
        }
    }
}

class ThreadB extends Thread {
    private WorkObject workObject;

    public ThreadB(WorkObject workObject) {
        this.workObject = workObject;
    }

    public void run() {
        for(int i = 0; i < 10; i++) {
            workObject.methodB();
        }
    }

JVM

  • JVM은 자바로 작성한 소스 코드를 해석해 실행하는 별도의 프로그램
  • 프로그램이 자신이 필요한 컴퓨터 자원을 운영체제에게 주문하면, 운영체제는 가용한 자원을 확인한 다음, 프로그램이 실행되는 데에 필요한 컴퓨터 자원을 프로그램에게 할당
  • 프로그램이 운영체제에게 필요한 컴퓨터 자원을 요청하는 방식이 운영체제마다 다름 →프로그래밍 언어의 운영체제에 대한 종속성
  • JVM이 자바 프로그램과 운영체제 사이에서 일종의 통역가 역할을 수행 →JVM은 자바 소스 코드를 운영 체제에 맞게 변환해 실행시켜줍니다. 이것이 자바가 운영체제로부터 독립적으로 동작

**Garbage Collection**

  • 아무한테도 참조되고 있지 않은 객체 및 변수들을 검색하여 메모리에서 점유를 해제하며, 그럼으로써 메모리 공간을 확보하여 효율적으로 메모리를 사용할 수 있게 해준다.

어려운 내용(에러)


문제

해결

profile
백엔드 개발자

0개의 댓글