프로그래밍 관련/언어들의 코딩들 C++ JAVA C# 등..

java Thread 관련 사용 방법 쓰기 정지 방법 관련.

AlrepondTech 2020. 9. 13. 19:13
반응형

 

 

 

=================================

=================================

=================================

 

 

 

 

 

 

 

White -box Thread

class ETest  extends Thread{
     // run() overring 함
      public void run(){
            System.out.println("Thread 상속");
      }
}
public class ExtendThreadTest{
      public static void main(String args[]){
            Thread ex = new ETest();
            // Thread 시작함
            // 위에서 ETest  ex = new ETest() 해도 됨
            // 상속 객체가 Thread라 Thread로 받은 것임
            ex.start();
      }
}


Black-Box

class RTest implements Runnable{
      public void run() {
            System.out.println("Runnable interface 구현");
      }
 }

public class RunnableThreadTest {
      public static void main(String args[]){
            // Thread 생성자에 Runnable interface 전달
            // RTest t = new RTest(); // t를 넣어도 됨(Upcasting 일어남)
            Thread t = new Thread(new RTest());
            t.start();
            t.wait();  //대기
            t.notify(); // 대기 해제
            t.sleep(5000); // 5초간 멈춤
      }
}

상속 : White-box reuse
합성 : Black-box reuse

Favor object composition over class inheritance
--> 객체 합서이 클래스 상속보다 나은 방법이다. GoF의 디자인 패턴

상속의 단점
캡슐화 위배 : 상속을 하면 super class의 내부가 노출된다.

Thread 구현 클래스 내서 Thread 동작 시키기
new Thread(this).start();

NotRunnable Status : 대기 상태 (Dead 상태 아님) --> sleep(시간), wait()
                      wait() 해제 --> notify()
                      위 상태로 만들 경우 InterruptedException 처리 해야 함


우선권 제어
- static int MAX_PRIORITY = 10
- static int MIN_PRIORITY = 1
- static int NORM_PRIORITY = 5
 setPriority(int) --> 우선 순위 설정
 getPriority() --> 우선권 얻기

[예제-우선 순위 출력]

more..

============= 우선권 내용 =================
10 : 위기 관리 (가장 빠름)
7~9 : 상호 작용, 이벤트 처리
4~6 : IO관련 작업
2~3 : 백그라운드 작업
1 : 기타 다른 작업이 없을 때 실행 (가장 느림)
==========================================

Thread 종료
플래그 사용 - 권장 사항
/**
* Sun 사에는 Thread 멈출때 stop 메소드를 권장하고 있지 않음
* 아래와 같이 plug 로 멈추게하는 것이 좋음
* 또한 run()안에 내용이 길다면 중간 중간에 stoped 필드를 체크해서 멈추는것을
* 확인해 줘야 함
 */
[예제 - 플래그를 사용한 Thread 정지]

more..

만약 모든 Thread를 한꺼번에 종료 관리 하기 위해서는
위 변수를 static으로 하면 됨
각각 관리하고 모든 Thread 종료도 하게 하려면

public static  boolean  all_exit = false;
private  boolean flag = false;

while(!flag  && !all_exit){

}

Interrupt 사용
- 잘 사용하지 않음
[예제-interrupt를 사용한 중지]

more..



Synchronization (동기화)
- synchronization처리를 하면 해당 메소드 또는 구간이 접근 중일때는
  다른 프로세스(쓰레드)는 접근하지 못함

Method 동기화
public  synchronized  void  metthodName(){
  ....
}

블록 동기화
public void methodName(){
    synchronized(this){
      // 블록 내에 사용된 this 즉 현재 클래스의 멤버 변수 동기화 이루어짐
    }
}

- 위 this는 공유 자원이 this 접근 가능한 멤버 변수 일때 사용함
- 만약 특정 변수에 블록 동기화를 하고자 하면 (Ex) 
    public void  run(){
        Test  t = Test();
        synchronized(t.name){
             ....
        }
    }
[예제 - 비디오 대여 관련 Thread처리 및 동기화]

 

 

 

=================================

=================================

=================================

 

 

 

출처: http://jangsalt.tistory.com/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://zeroit.tistory.com/25

 

쓰레드(Thread)란, 프로그램의 실행 흐름으로서, 일반적으로 프로그램이 시작되며 main 메소드가 호출되고 하나의 메인 쓰레드를 지니게 됩니다. 프로그램에 따로 쓰레드를 생성하여 관리하는 코드가 없다면 프로그램은 시작부터 끝가지 단 하나의 쓰레드를 지니게되며 이런 프로그램을 싱글쓰레드 프로그램이라 합니다.

 

요즘 대부분의 CPU들은 다중코어 아키텍처를 택하고 있기때문에, CPU의 능력을 최대한 활용하기 위해서는 싱글쓰레드로 프로그램보다는 다수의 쓰레드를 두어 병렬처리가 가능하도록 설계된 멀티쓰레드 프로그램이 좋습니다.

 

1. Thread 클래스

Java에서 쓰레드를 생성하기 위해서 Thread 클래스를 상속하여 이용하거나, Runnable 인터페이스를 구현하여 Thread 객체를 생성할수 있습니다. 2가지 방법 모두 쓰레드를 사용하는데 문제는 없으나 Thread 클래스를 직접 상속하여 run 메소드를 오버라이드 하는 방법보다는 Runnable 인터페이스를 이용하는 방법을 추천합니다.(Java에서는 다중 상속이 불가능 하기때문에 Thread를 상속하는 방법은 다른 클래스를 상속받을수 없음을 의미합니다.)

view plaincopy to clipboardprint?

  1. class MyThread extends Thread {    
  2.     @Override  
  3.     public void run() {  
  4.         // TODO here  
  5.     }  
  6. }  
  7.   
  8. public class ThreadTest {  
  9.     public static void main(String[] args) {  
  10.         MyThread t = new MyThread();  
  11.         t.start();  
  12.         t.join();  
  13.     }  
  14. }  

view plaincopy to clipboardprint?

  1. public class ThreadTest {  
  2.     public static void main(String[] args) {  
  3.         Thread t = new Thread(new Runnable() {  
  4.             @Override  
  5.             public void run() {  
  6.                     // TODO here      
  7.             }  
  8.         });  
  9.         t.start();  
  10.         t.join();  
  11.     }  
  12. }  

 

2. 쓰레드 종료

쓰레드는 run메소드가 종료할때까지 유지되는데, 일반적으로 많은 워커쓰레드는 내부에 무한루프를 지니며, 외부의 입력조건에 따라 쓰레드를 종료시키는 구조를 지니고 있습니다. 자바에서 스레드를 종료할 때는 상태변수(state variable)를 사용해 run() 메소드를 탈출하는 방식을 사용하는데, 이 것을 "state based" singnaling이라 합니다. 기존에 제공되던 Thread.stop(), Thread.suspend(), Thread.resume()은 더 이상 사용할 수 없습니다.

view plaincopy to clipboardprint?

  1. class MyThread extends Thread {    
  2.       
  3.     private volatile boolean isRun = true;  
  4.       
  5.     public void setRun(boolean isRun) {  
  6.         this.isRun = isRun;  
  7.     }  
  8.   
  9.     @Override  
  10.     public void run() {  
  11.         while( isRun ) {  
  12.             // TODO here      
  13.         }  
  14.     }  
  15. }  
  16.   
  17. public class ThreadTest {  
  18.     public static void main(String[] args) {  
  19.         MyThread t = new MyThread();  
  20.         // TODO here  
  21.         t.setRun(false);  
  22.     }  
  23. }  

view plaincopy to clipboardprint?

  1. class MyThread extends Thread {    
  2.     @Override  
  3.     public void run() {  
  4.         try {  
  5.             whiletrue ) {  
  6.                 // TODO here  
  7.             }  
  8.         } catch (InterruptedException e) {  
  9.             Thread.currentThread().interrupt();  
  10.             return;  
  11.         }  
  12.     }  
  13. }  
  14.   
  15. public class ThreadTest {  
  16.     public static void main(String[] args) {  
  17.         MyThread t = new MyThread();  
  18.         // TODO here  
  19.         t.interrupt();  
  20.     }  
  21. }  

첫번째 방법은 직접 상태변수를 선언하고 그 것을 이용하는 것입니다. 자기 쓰레드의 종료 상태를 지정할 수 있는 상태변수(r/w enabled)를 변수로  정의하고, run() 메소드 내에서 주기적으로 종료 상태를 검사해서 메소드를 탈출(리턴)합니다. 상태변수는 volatile로 선언되거나 또는, 동기화된(synchronized) 방법으로 접근되어야 함에 주의해야합니다.

 

두번째 방법은 Thread.interrupt()를 이용하는 것입니다. VM 내부적으로 intrrupt status라는 내부변수를 사용하며, 위의 방법으로 다룰 수 없는 상태의 스레드를 종료하는 데 사용할 수 있습니다. 즉, wait(), wait(long), wait(long, int), 또는 join(), join(long), join(long, int), static sleep(long), static sleep(long, int) 등으로 블럭된(blocked state) 스레드의 경우에 해당 스레드 객체를 통해서 Thread.interrupt()를 호출하는 즉시, 블럭해제됨과 동시에 InterruptedException을 발생시킨후 interrupt status는 초기화(clear)됩니다.. 따라서 try 구문의 catch 블럭 내에서 적당한 종료 코드를 작성하여 쓰레드를 종료할 수 있으며, run() 메소드 외부에서 InterruptedException을 캐치한 경우에는, InterruptException을 rethrow 하거나, Thread.currentThread().interrupt()를 reassert함으로써 run()메소드까지 interrupt status가 전달되도록 해야 할수 있습니다. intrrupt status의 상태는 static Thread.interrupted()를 통해서 검사할 수 있습니다.

 

 

 

=================================

=================================

=================================

 

 

반응형