/ JAVAJUNGSUK

Ch13-22~25. sleep()

자바의 정석 기초편

0. 목차



Chapter13. 쓰레드

Ch13 - 22. sleep()

Ch13 - 23. sleep() 예제

Ch13 - 24. interrupt()

Ch13 - 25. interrupt() 예제



Ch13 - 22. sleep()


▶ sleep()이란?

▷ 현재 쓰레드를 지정 된 시간 동안 멈추에 함
▷ static 메서드 : 자기 자신에게만 동작
static void sleep(long millis) // 잠 잘 시간을 설정, 3000 = 3초
static void sleep(long millis, int nanos)
  • millis = 1/1000초 = 10-3
  • nanos = 1/1000000000초 = 10-9
▷ 특정 쓰레드를 지정하여 멈추게 하는 것 불가능
try {
    th1.sleep(1, 500000) // th1을 sleep() 시킨다?, 에러는 안나지만 오해할 수 있음
} catch(InterruptedException e) { }

// ↓↓↓↓ 변경 ↓↓↓↓
try {
    Thread.sleep(1, 500000) // Thread를 적어 줌
} catch(InterruptedException e) { }


▶ sleep()을 깨우는 방법

▷ InterruptedException 발생 시 깨어남
  • sleep() code
    // sleep() = InterruptedException을 필수로 갖고있는 메서드
    public static native void sleep(long millis) throws InterruptedException;
    
  • InterruptedException code
    // InterruptedException = Exception을 상속받음
    public class InterruptedException extends Exception
    
  • sleep() 사용 시, try-catch문 반드시 작성
      try {
          Thread.sleep(1, 500000) // 쓰레드를 0.0015초 동안 멈춤
      } catch(InterruptedException e) { }
      
      // ↓↓↓↓ 계속 만들지 않고 메서드에 담을 수 있음 ↓↓↓↓
      static void delay(long millis) {
        try {
          Thread.sleep(millis)
        } catch(InterruptedException e) { }
      }
      
      // ↓↓↓↓ delay 메서드를 사용하려면? ↓↓↓↓
      delay(15); // 0.0015초 동안 멈춤
    
    • 0.0015초 동안 try에서 throw new InterruptException이 발생하면
    • catch문 실행하여 sleep() 깨움
▷ time up
  • 시간 종료



Ch13 - 23. sleep() 예제


▶ 2초 잠든 후 main 메서드 종료

▷ 직접 sleep 코드 작성하여 사용
class Ex13_8 {
	public static void main(String args[]) {
		ThreadEx8_1 th1 = new ThreadEx8_1();
		ThreadEx8_2 th2 = new ThreadEx8_2();
		th1.start(); th2.start();

		try {
			Thread.sleep(2000);	// th1.sleep() 이라 적지 않음, 오해 만들지 않기
		} catch(InterruptedException e) {}

		System.out.print("<<main 종료>>");
	} // main
}

class ThreadEx8_1 extends Thread {
  public void run() {
    for(int i=0; i < 300; i++) System.out.print("-");
    System.out.print("<<th1 종료>>");
  } // run()
}

class ThreadEx8_2 extends Thread {
  public void run() {
    for(int i=0; i < 300; i++) System.out.print("|");
    System.out.print("<<th2 종료>>");
  } // run()
}

// console
--|||||||||||||||||||||||||||||||||||||||||||||||---|||||||||||||||||||||||||||||||||||||||
||||||||||||||||||||||||--------------------------------------||||||||||||||||||||||||-----
-----------------------------------|||||||||||||||||||||----------|||||||||||||||||||||||||
||||||||||---------------------------------------------------------------------------------
-----------------------------------------------||||||||||||||||||||||||||||||||||||||||||||
||||||||||||||||||||||||||||--------------------------------------------------------------|
||||||-|||||||||||||||||||||||||||||||<<th2 종료>>----------------<<th1 종료>><<main 종료>>
  • <<th2 종료>> → <<th1 종료>> -2초 후→ <<main 종료>>
▷ 메서드 생성하여 호출하여 사용
class Ex13_8 {
	public static void main(String args[]) {
		ThreadEx8_1 th1 = new ThreadEx8_1();
		ThreadEx8_2 th2 = new ThreadEx8_2();
		th1.start(); th2.start();

		delay(2000);
		
		System.out.print("<<main 종료>>");
	} // main
	
	static void delay(long millis) {
		try {
			Thread.sleep(millis);
		} catch(InterruptedException e) { }
	}
}


Ch13 - 3. interrupt()


▶ interrupt()란?

▷ 대기 상태(WAITING)인 쓰레드를 실행 대기 상태(RUNNABLE)로 만듦
  • 대기 상태 : sleep(), join(), wait()

▶ interrupt()의 관련 메서드

▷ void interrupt()
  • 쓰레드의 interrupted 상태를 false에서 true로 변경
▷ boolean isInterrupted()
  • 쓰레드의 interrupted 상태를 반환
  • 잠을 자고 있었는데 누가 깨워서 일어났는지, 다 자고 일어났는지 확인 가능
▷ static boolean interrupted()
  • 현재 쓰레드의 interrupted 상태를 알려주고, false로 초기화

  • Thread code

    class Thread {
      ...
      boolean interrupted = false; // 자는 중
      ...
      boolean isInterrupted() { return interrupted; } // isInterrupted는 false로 초기화 안함, 계속 true상태 유지
        
      boolean interrupt() { interrupted = true; } // interrupt() 호출하면 잠 깨니까 true
    }
    
▷ 예시1
public static void main(String[] args) {
  ThreadEx13 th1 = new ThreadEx13();
  th1.start();
  ...
  th1.interrupt(); // interrupt() 호출 시, interrupted 상태가 true가 됨, 잠 깸

  System.out.println("isInterrupted() : " + th1.isInterrupted());
}

// console
isInterrupted() : true // 깼으니까 true
▷ 예시2
  • 다운로드 중 취소 버튼 클릭 → interrupt() 발생
    class ThreadEx13 extends Thread {
      public void run() {
        ...
            
        // download를 수행
        while(downloaded && !isInterrupted()) {
        ...
        }
      }
    }
    
    • 취소 클릭 시, isInterrupted 상태 : false → true
    • !isInterrupted() 이므로 정확히 isInterrupted 상태 : !false → !true
    • !false → !true : true → false


Ch13 - 3. interrupt() 예제


▶ boolean isInterrupted()

▷ th1.isInterrupted()
▷ th1.interrupt() → th1.isInterrupted()
▷ th1을 깨우고 상태 반환
▷ 깨웠으니까 th1.isInterrupted() = true 반환
import javax.swing.JOptionPane;

class Ex13_9 {
public static void main(String[] args) throws Exception {
ThreadEx9_1 th1 = new ThreadEx9_1();
th1.start();

		String input = JOptionPane.showInputDialog("아무 값이나 입력하세요."); 
		System.out.println("입력하신 값은 " + input + "입니다.");
		System.out.println("isInterrupted():"+ th1.isInterrupted());
		th1.interrupt();  // interrupt()를 호출 시 interrupted = true
		System.out.println("isInterrupted():"+ th1.isInterrupted());
		System.out.println("isInterrupted():"+ th1.isInterrupted());
	}
}

class ThreadEx9_1 extends Thread {
public void run() {
int i = 10;

		while(i!=0 && !isInterrupted()) {
			System.out.println(i--);
			for(long x=0;x<2500000000L;x++); // 시간 지연
		}
		System.out.println("카운트가 종료되었습니다.");
	} 
}

// console
10
9
8
입력하신 값은 1515입니다.
isInterrupted():false
isInterrupted():true
isInterrupted():true
카운트가 종료되었습니다.


▶ static boolean interrupted()

▷ static은 자기 자신만 깨울 수 있음
th1.interrupted() → Thread.interrupted()
▷ Thread.interrupted() : 여기서 Thread는 현재 쓰레드, main 쓰레드
▷ interrupt로 깨운 건 th1, main 쓰레드는 깨운 적 없음
▷ Thread.interrupted() : 현재 쓰레드인 main 쓰레드를 interrupt 했는가?
import javax.swing.JOptionPane;

class Ex13_9 {
	public static void main(String[] args) throws Exception {
		ThreadEx9_1 th1 = new ThreadEx9_1();
		th1.start();

		String input = JOptionPane.showInputDialog("아무 값이나 입력하세요."); 
		System.out.println("입력하신 값은 " + input + "입니다.");
		System.out.println("isInterrupted():"+ th1.isInterrupted());
		th1.interrupt();  // interrupt()를 호출하면, interrupted상태가 true가 된다.
		System.out.println("isInterrupted():"+ th1.isInterrupted());
		System.out.println("isInterrupted():"+ th1.isInterrupted());
		System.out.println("interrupted():"+ Thread.interrupted());
		System.out.println("interrupted():"+ Thread.interrupted());
	}
}

class ThreadEx9_1 extends Thread {
	public void run() {
		int i = 10;

		while(i!=0 && !isInterrupted()) {
			System.out.println(i--);
			for(long x=0;x<2500000000L;x++); // 시간 지연
		}
		System.out.println("카운트가 종료되었습니다.");
	} 
}

// console
10
9
8
7
입력하신 값은 9999입니다.
isInterrupted():false
isInterrupted():true
isInterrupted():true
interrupted():false
interrupted():false
카운트가 종료되었습니다.


▶ th1에서 확인 해 보기

▷ this.isInterrupted() : this 쓰레드가 interrupt 된 상태
▷ Thread.interrupted() : 현재 쓰레드가 interrupt 했는가?
import javax.swing.JOptionPane;

class Ex13_9 {
	public static void main(String[] args) throws Exception {
		ThreadEx9_1 th1 = new ThreadEx9_1();
		th1.start();

		String input = JOptionPane.showInputDialog("아무 값이나 입력하세요."); 
		System.out.println("입력하신 값은 " + input + "입니다.");
		
		th1.interrupt();  // interrupt()를 호출하면, interrupted상태가 true가 된다.
	}
}

class ThreadEx9_1 extends Thread {
	public void run() {
		int i = 10;

		while(i!=0 && !isInterrupted()) {
			System.out.println(i--);
			for(long x=0;x<2500000000L;x++); // 시간 지연
		}
		System.out.println("isInterrupted():"+ this.isInterrupted());
		System.out.println("isInterrupted():"+ this.isInterrupted());
		System.out.println("isInterrupted():"+ this.isInterrupted());
		System.out.println("interrupted():"+ Thread.interrupted());
		System.out.println("interrupted():"+ Thread.interrupted());
		System.out.println("카운트가 종료되었습니다.");
	} 
}

// console
10
9
8
입력하신 값은 1515입니다.
isInterrupted():true
isInterrupted():true
isInterrupted():true
interrupted():true
interrupted():false
카운트가 종료되었습니다.
  • interrupted() : 현재 쓰레드는 interrupt 됨 true 반환
  • interrupted()false로 초기화 시켜 둠