독학/자바

[혼공학습단 10기] 자바 week4

최연재 2023. 7. 29. 17:54

미션

기본미션 : p. 550 [직접 해보는 손코딩] 코딩 과정 및 실행 결과 캡처하기

// AutoSaveThread.java

package sec02.exam05;

public class AutoSaveThread extends Thread{
	public void save() {
		System.out.println("작업 내용을 저장함.");
	}
	
	@Override
	public void run() {
		while (true)
		{
			try {
				Thread.sleep(1000);
			} catch(Exception e) {
			break;
			}
			save();
		}
	}
}
// DaemonExample.java

package sec02.exam05;

public class DaemonExample {
	public static void main(String[] args) {
		AutoSaveThread autoSaveThread = new AutoSaveThread();
		autoSaveThread.setDaemon(true);
		autoSaveThread.start();
		
		try {
			Thread.sleep(3000);
		} catch(Exception e) {
		}
		
		System.out.println("메인 스레드 종료");
	}
}

 

선택미션 : p. 539 문제 2번 풀고, 풀이 과정 설명하기

// ThreadExample.java

package sec01.verify.exam02;

public class ThreadExample {
	public static void main(String[] args) {
		Thread thread1 = new MovieThread();
		thread1.start();
		
		Thread thread2 = new Thread(new MusicRuunable());
		thread2.start();
	}
}
  • ① new MusicRuunable()
  • Thread 클래스로부터 작업 스레드 객체를 생성하기 위해서는 Runnable을 매개값으로 갖는 생성자를 호출해야 함
  • 따라서 MusicRunnable 구현 객체를 생성하고 이를 매개값으로 Thread 생성자를 호출
// MovieThread.java

package sec01.verify.exam02;

public class MovieThread extends Thread {
	@Override
	public void run() {
		for (int i=0; i<3; i++){
			System.out.println("동영상을 재생합니다.");
			try {Thread.sleep(1000);} catch(Exception e) {}
		}
	}
}
  • ② extends Thread
  • 작업 스레드가 실행할 작업을 Runnable로 만들지 않고 Thread의 하위 클래스로 작업 스레드를 정의하면서 작업 내용을 포함시킬 수도 있음 -> Thread 클래스를 상속
// MusicRuunable.java

package sec01.verify.exam02;

public class MusicRuunable implements Runnable{
	@Override
	public void run() {
		for (int i=0; i<3; i++){
			System.out.println("음악을 재생합니다.");
			try {Thread.sleep(1000);} catch(Exception e) {}
		}
	}
}
  • ③ implements Runnable
  • Runnable 구현 클래스를 작성

Chapter 12 스레드

1. 멀티 스레드

📍프로세스 : 운영체제에서 실행 중인 하나의 애플리케이션

 

📌 스레드

- 운영체제는 두 가지 이상의 작업을 동시에 처리하는 멀티 태스킹을 할 수 있도록 CPU 및 메모리 자원을 프로세스마다 적절히 할당해주고, 병렬로 실행시킨다.

- 멀티 프로세스는 자신의 메모리를 가지고 실행하므로 서로 독립적이다.

- 멀티 스레드는 하나의 프로세스 내부에 생성된다.

 

📌 메인 스레드

- 자바의 모든 애플리케이션은 메인 스레드가 main() 메소드를 실행하면서 시작된다.

- 메인 스레드는 필요에 따라 멀티 스레드를 생성해서 멀티 태스킹을 수행한다.

 

📌 작업 스레드 생성과 실행

- Thread 클래스로부터 직접 생성

  • Runnable을 매개값으로 갖는 생성자 호출
Runnable task = new Task();
Thread thread = new Thread(Runnable target);
  • Runnable은 인터페이스 타입이기 때문에 구현객체를 만들어 대입해야 함. 
  • Runnable에 run() 메소드가 정의되어 있는데 구현클래스는 run()을 재정의해서 작업 스레드가 실행할 코드를 작성해야 함.
class Task implements Runnable {
    public void run() {
    // 스레드가 실행할 코드;
    }
}
  • Thread 생성자를 호출할 때 Runnable 익명 객체를 매개값으로 사용할 수 있다.
Thread thread = new Thread(new Runnable() {
    public void run() {
    // 스레드가 실행할 코드;
    }
});
  • 작업 스레드는 생성되는 즉시 실행되는 것이 아니라, start() 메소드를 호출해야 함.
thread.start();

- Thread 하위 클래스로부터 생성

  • 작업 스레드가 실행할 작업을 Runnable로 만들지 않고, Thread의 하위 클래스로 작업 스레드를 정의하면서 작업 내용을 포함시킬 수 있음.
public class WorkerThread extends Thread {
    @Override
    public void run() {
    // 스레드가 실행할 코드;
    }
}
Thread thread = new WorkerThread();
  • Thread 익명 객체로 작업 스레드 객체를 생성할 수 있다.
Thread thread = new Thread() {
    public void run() {
    // 스레드가 실행할 코드;
    }
}

- 스레드의 이름

  • 스레드의 이름이 큰 역할을 하는 것은 아니지만, 디버깅할 때 어떤 스레드가 어떤 작업을 하는지 조사할 목적으로 사용하기도 함.
  • 메인 스레드는 'main'이라는 이름을 가지고 있고, 생성한 스레드는 자동적으로 이름이 'Thread-n'으로 설정된다. (n은 스레드의 번호)
  • 이름을 직접 설정하고 싶다면 Thread 클래스의 setName() 메소드로 변경할 수 있다.
  • 스레드의 이름을 알고 싶을 때는 getName() 메소드를 호출하면 된다.
  • setName(), getName()은 Thread 클래스의 인스턴스 메소드이므로 스레드 객체의 참조가 필요하다.
  • 현재 스레드객체의 참조를 가지고 있지 않다면 currentThread()를 이용해서 현재 스레드의 참조를 얻을 수 있다. 
Thread thread = Thread.currentThread();

thread.setName("스레드 이름");
thread.getName();

 

📌 동기화 메소드

-  공유 객체 사용 시 주의점 : 하나의 스레드가 사용하던 객체를 다른 스레드가 접근 가능하므로 원치 않은 결과 초래 가능

- 동기화 메소드

  • 스레드가 사용 중인 객체를 다른 스레드가 변경할 수 없도록 스레드 작업이 끝날 때까지 객체에 잠금을 걸어야 함.
  • 임계 영역 : 멀티 스레드 프로그램에서 단 하나의 스레드만 실행할 수 있는 코드 영역
  • 동기화 메소드 : 임계 영역을 지정하기 위해 사용
public synchronized void method() {
    // 임계 영역;
}

 

2. 스레드 제어

📌 스레드 상태

- 스레드 객체를 생성하고 start() 메소드를 호출하면 실행 대기 상태가 된다.

- 실행 대기 상태에 있는 스레드 중에서 운영체제는 하나의 스레드를 선택하고 CPU가 run() 메소드를 실행하도록 하면 실행 상태가 된다.

- 스레드는 실행 대기 상태와 실행 상태를 번갈아가면서 run() 메소드를 조금씩 실행한다.

- 실행 상태에서 run() 메소드가 종료되면 종료 상태가 된다.  

- 스레드가 실행될 수 없는 상태를 일시 정지 상태라고 한다.

 

📌 스레드 상태 제어

- 스레드 상태 제어 : 실행 중인 스레드의 상태를 변경하는 것

- 상태를 변화시키는 메소드의 종류

  • interrupt() : 일시 정지 상태의 스레드에서 InterruptedException을 발생시켜, 예외 처리 코드에서 실행 대기 상태나 종료 상태로 갈 수 있음.
  • sleep(long millis) : 주어진 시간 동안 스레드를 일시 정지 상태로 만듦. 주어진 시간이 지나면 자동으로 실행 대기 상태가 됨.
  • stop() : 스레드를 즉시 종료. 불안정한 종료를 유발하므로 사용하지 않는 것이 좋음.

- 주어진 시간 동안 일시 정지 : sleep()

try {
    Thread.sleep(1000);
} catch(InterruptedException e) {
    // interrupt() 메소드가 호출되면 실행
}

- 스레드의 안전한 종료 : 실행 중인 스레드를 즉시 종료하기

① stop 플래그 이용

public class XXXThread extends Thread{
    private boolean stop; // stop 플래그 빌드
    
    public void run() {
        while (!stop) {
        // 스레드가 반복실행하는 코드
        }
        // 스레드가 사용한 자원 정리
    }
}

② interrupt() 메소드 이용

  • 일시 정지 상태의 스레드에서 InterruptedException을 발생시켜, 예외 처리 코드 블록으로 이동
  • 스레드가 실행 대기 또는 실행 상태에 있을 때 interrupt() 메소드가 실행되면 즉시 InterruptedException이 발생하지 않고 스레드가 일시 정지 상태일 때 발생
  • 일시 정지를 만들지 않고 interrupt()의 호출 여부를 알기 위해 interrupted()나 isInterrupted() 메소드 사용 가능
boolean status = Thread.interrupted();
boolean status = objThread.isInterrupted();

 

 

📌 데몬 스레드

- 주 스레드의 작업을 돕는 보조적인 역할을 수행하는 스레드

- 주 스레드가 종료되면 데몬 스레드는 강제 종료됨.

- 스레드를 데몬 스레드로 만들기 위해서는 주 스레드가 데몬이 될 스레드의 setDaemon(true)를 호출한다.

public static void main(String[] args) {
    AutoSaveThread thread = new AutoSaveThread();
    thread.setDaemon(true);
    thread.start();
}

스레드는 처음이라 많이 어려웠습니다.... 다음 주는 쉬어가는 주이니 열심히 복습해서 돌아오겠습니다💪

+) 여담

족장님 제가 2주차 우수혼공족이라서 받은 기프티콘으로 바닐라 아메리카노 먹어봤는데 맛있어요!! 아이스 바닐라 라떼와 아메리카노 사이 느낌입니다..ㅎㅎ 우수혼공족으로 받은 기프티콘 사용하면서 열심히 공부 중입니다😍

'독학 > 자바' 카테고리의 다른 글

[혼공학습단 10기] 자바 week6  (0) 2023.08.15
[혼공학습단 10기] 자바 week5  (0) 2023.08.08
[혼공학습단 10기] 자바 week3  (0) 2023.07.19
[혼공학습단 10기] 자바 week2  (0) 2023.07.16
[혼공학습단 10기] 자바 week1  (0) 2023.07.09