Notice
Recent Posts
Recent Comments
Link
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
Tags
more
Archives
Today
Total
관리 메뉴

시다바리

[Java] Thread의 정지 본문

Language/Java

[Java] Thread의 정지

호서아빠 2008. 9. 9. 16:22
Thread.stop가 추천 되지 않는 이유

본질적으로 안전하지 않기 때문입니다.
Thread를 정지하면, 그 Thread가 잠근 모든 모니터의 락이 해제됩니다.
(ThreadDeath 예외가 스택까지 전해지면, 모니터의 락이 해제된다.)
이러한 모니터에 의해서 이전 보호되고 있던 오브젝트가 정합성이 없는 상태가 되면, 다른 Thread도, 이러한 오브젝트가 정합성의 없는 상태에 있다고 봅니다.
그러한 오브젝트는 망가진오브젝트가 됩니다.
망가진 오브젝트에 대해서 Thread가 조작을 실행하면, 예기치 않은 결과가 될 가능성이 있습니다. 이 동작은, 미묘하고 검출이 곤란한 경우와 확실히 통지되는 경우가 있습니다.
체크되지 않는 것 외의 예외와는 달라,ThreadDeath는, 스렛드를 그대로 강제적으로 종료합니다. 이 때문에 유저는 프로그램이 망가질 가능성이 경고되지 않습니다.
프로그램이 망가지거나, 실제로 손상을 받은 것이 나중에 밝혀지게 됩니다.

Thread.stop 대신에 무엇을 사용해야 하는가

stop 의 대신으로 대부분이 타겟스레드의 실행을 정지해야 할 일을 나타내는 변수를 변경하는 코드를 사용합니다.
타겟스레드는 이 변수를 정기적으로 검사해 실행을 정지해야 할 일을 변수가 나타내 보이고 있는 경우에스레드의 run 메소드로부터 통상의 방법으로 복귀할 필요가 있습니다.
이것은 Java 소프트웨어의 튜토리얼에서 추천 하고 있는 방법입니다.
정지 요구의 즉시 통신을 확실히 하려면 변수를 volatile으로 하거나 변수에서 액세스를 동기화해야 할 필요가 있습니다.

예를 들어, 애플릿에 다음의 start,stop, 및 run 메소드가 포함되어 있다고 합니다.
private Thread blinker;

public void start() {
  blinker = new Thread(this);
  blinker.start();
}

public void stop() {
  blinker.stop(); // UNSAFE!
}

public void run() {
  Thread thisThread = Thread.currentThread();
  while (true) {
    try {
      thisThread.sleep(interval);
    } catch (InterruptedException e){
    }
    repaint();
  }
}
애플릿의 stop 및 run 메소드를 다음의 코드와 옮겨놓는 것으로 Thread.stop을 사용하지 않고 끝납니다.
private volatile Thread blinker;

public void stop() {
  blinker = null;
}

public void run() {
  Thread thisThread = Thread.currentThread();
  while (blinker == thisThread) {
    try {
      thisThread.sleep(interval);
    } catch (InterruptedException e){
    }
    repaint();
  }
}

오랫동안 (입력 등을) 대기하고 있는 스레드는 어떻게 하면 정지할 수 있습니까

그 목적으로는,Thread.interrupt 을 사용합니다.위와 같을 상태에 대해 응하는시그널 기구를 사용할 수 있습니다만,상태 변경 (앞의 예에서는 blinker = null) 후에, Thread.interrupt을 호출해 대기 상태에 끼어들 수 있습니다.
public void stop() {
  Thread moribund = waiter;
  waiter = null;
  moribund.interrupt();
}
이 방법에서는, 세치기 예외를 캐치 하지만, 처리할 준비가 되어 있지 않은 메소드는 그 예외를 재선언하는 것이 중요합니다.
여기서 「재쓰로우」는 아니고 「재선언」이라고 쓴 것은, 예외를 언제나 재슬로우 할 수 있다고는 할 수 없기 때문입니다.
InterruptedException을 캐치 한 메소드가, 확인이 끝난 예외를 스로우 하도록 선언되어 있지 않은 경우는,다음과 같은 정해진 규칙에 의해 스스로 재할당을 할 필요가 있습니다.

Thread.currentThread().interrupt();
이것에 의해, 스레드는, 가능한 한 빨리 InterruptedException을 재발행할 수 있게 됩니다.

스레드가 Thread.interrupt에 응답하지 않으면 어떻게 됩니까

어플리케이션 독자적인 기법이 사용 가능한 경우도 있습니다.
예를 들어, 스렛드가 기존의 소켓상에서 대기하고 있는 경우는, 소켓을 닫는 것으로 스렛드를 즉시 복귀시킬 수 있습니다.
그러나, 유감스럽지만, 범용적으로 사용할 수 있는 기법은 없습니다.
대기하고 있는 스렛드가 Thread.interrupt 에 응답하지 않는 모든 상황에서는,
그 스렛드는 Thread.stop 에도 응답하지 않는 것에 주의해 주세요.
그러한 상황으로서는,의도적인 서비스 방해 공격이나 ,thread.stop과 thread.interrupt가적절히 기능하지 않는 입출력 조작등이 있습니다.

나) 결론을 말하자면 stop은 비추천이므로 다른 방법중에 .. 루프등 돌면서 선언해둔 변수가, 끝나는 지점인가 등을 통해종료 할 수 밖에 없다. 다른 방법이 있으면 좀 알려주었으면 ...

출처 : http://blog.empas.com/urusaina/26851511
Comments