JavaRush /Java Blog /Random-KO /멀티스레딩: 스레드 클래스 메서드가 수행하는 작업

멀티스레딩: 스레드 클래스 메서드가 수행하는 작업

Random-KO 그룹에 게시되었습니다
안녕하세요! 오늘 우리는 멀티스레딩에 대해 계속 이야기합니다. Thread 클래스와 해당 클래스의 여러 메서드가 어떻게 작동하는지 살펴보겠습니다. 이전에는 클래스 메서드를 공부할 때 "메서드 이름" -> "무엇을 하는지"와 같이 간단하게 작성하는 경우가 가장 많았습니다.
멀티스레딩: Thread 클래스의 메서드가 수행하는 작업 - 1
이는 Thread 메서드에서는 작동하지 않습니다. :) 해당 논리는 더 복잡하고 몇 가지 예제가 없으면 이해하는 것이 불가능합니다.

Thread.start() 메서드

반복부터 시작해 보겠습니다. 아마 기억하시겠지만, 클래스에서 클래스를 상속하고 Thread그 안에 있는 메서드를 재정 의하여 스레드를 만들 수 있습니다 run(). 하지만 물론 저절로 시작되지는 않습니다. 이를 위해 객체에서 메소드를 호출합니다 start(). 멀티스레딩: Thread 클래스의 메서드가 수행하는 작업 - 2이전 강의의 예를 기억해 봅시다.
public class MyFirstThread extends Thread {

   @Override
   public void run() {
       System.out.println("Выполнен поток " + getName());
   }
}


public class Main {

   public static void main(String[] args) {

       for (int i = 0; i < 10; i++) {
           MyFirstThread thread = new MyFirstThread();
           thread.start();
       }
   }
}
참고: 스레드를 시작하려면!start()메소드가 아닌run()이는 특히 멀티스레딩을 처음 배울 때 저지르기 쉬운 실수입니다. run()이 예에서 대신개체에 대한 메서드를 10번 호출하면start()결과는 다음과 같습니다.
public class Main {

   public static void main(String[] args) {

       for (int i = 0; i < 10; i++) {
           MyFirstThread thread = new MyFirstThread();
           thread.run();
       }
   }
}
스레드 0 스레드 실행 스레드 1 스레드 실행 스레드 2 스레드 실행 스레드 3 스레드 실행 스레드 4 스레드 실행 스레드 5 스레드 실행 스레드 6 스레드 실행 스레드 7 스레드 실행 스레드 8 스레드 실행 스레드 9 스레드 실행 출력 순서를 살펴보세요. 모든 것이 순서대로 진행됩니다. 이상하지 않나요? 스레드가 시작되고 실행되는 순서가 운영 체제 내부의 초지능인 스레드 스케줄러에 의해 결정된다는 것을 이미 알고 있기 때문에 우리는 이에 익숙하지 않습니다. 어쩌면 내가 운이 좋았던 건 아닐까? 물론 운의 문제는 아닙니다. 프로그램을 몇 번 더 실행하여 이를 확인할 수 있습니다. 요점은 메서드를 직접 호출하는 것이run()멀티스레딩과 아무 관련이 없다는 것입니다. 이 경우 프로그램은 메소드가 실행되는 메인 스레드에서 실행됩니다main(). 단순히 콘솔에 10줄을 순차적으로 출력하면 그게 전부입니다. 10개의 스레드가 시작되지 않습니다. 그러므로 미래를 기억하고 끊임없이 자신을 점검하십시오. 그 일이 이루어지길 원한다면run()그 사람에게 전화하세요start(). 계속 진행합시다.

Thread.sleep() 메서드

현재 스레드의 실행을 잠시 일시 중지하려면 sleep(). 멀티스레딩: Thread 클래스의 메서드가 수행하는 작업 - 3이 메서드는 sleep()밀리초(밀리초) 수, 즉 스레드를 절전 모드로 전환해야 하는 시간을 매개 변수로 사용합니다.
public class Main {

   public static void main(String[] args) throws InterruptedException {

       long start = System.currentTimeMillis();

       Thread.sleep(3000);

       System.out.println(" - Сколько я проспал? \n - " + ((System.currentTimeMillis()-start)) / 1000 + " секунды");

   }
}
콘솔 출력: - 얼마나 오랫동안 잠을 잤나요? - 3초 참고: 메서드 sleep()는 정적이므로 현재 스레드를 절전 모드로 전환합니다. 즉, 현재 작업중인 것입니다. 또 다른 중요한 뉘앙스: 수면 상태의 흐름이 중단될 수 있습니다. 이 경우 프로그램에서 예외가 발생합니다 InterruptedException. 아래에서 예를 살펴보겠습니다. 그런데 스레드가 "깨어난" 후에는 어떻게 되나요? 중단된 부분부터 즉시 실행을 계속합니까? 아니요. 스레드가 깨어난 후(인수로 전달된 시간이 만료되면 Thread.sleep()) 실행 가능 상태로 들어갑니다 . 그러나 이것이 스레드 스케줄러가 이를 실행한다는 의미는 아닙니다. 다른 "잠자지 않는" 스레드에 우선권을 부여하고 "새로 깨어난" 스레드는 조금 후에 계속 작동할 가능성이 높습니다. 꼭 기억하세요: "깨어났다고 해서 바로 그 순간에 계속해서 일한다는 뜻은 아닙니다!"

Thread.join() 메서드

멀티스레딩: Thread 클래스의 메서드가 수행하는 작업 - 4이 메서드는 join()다른 스레드가 완료될 때까지 현재 스레드의 실행을 일시 중단합니다. 2개의 스레드가 있고 , t1그리고 t2다음과 같이 쓴다면 -
t1.join()
t2t1이 작업을 완료할 때까지 작업을 시작하지 않습니다. 이 메소드는 join()스레드의 실행 순서를 보장하는 데 사용될 수 있습니다. join()예를 사용하여 작업을 살펴 ​​보겠습니다 .
public class ThreadExample extends Thread {

   @Override
   public void run() {

       System.out.println("Начало работы потока " + getName());

       try {
           Thread.sleep(5000);
       } catch (InterruptedException e) {
           e.printStackTrace();
       }
       System.out.println("Поток " + getName() +  " завершил работу.");
   }
}


public class Main {

   public static void main(String[] args) throws InterruptedException {

       ThreadExample t1 = new ThreadExample();
       ThreadExample t2 = new ThreadExample();

       t1.start();


 /*Второй поток t2 начнет выполнение только после того, How будет завершен
       (or бросит исключение) первый поток - t1*/
       try {
           t1.join();
       } catch (InterruptedException e) {
           e.printStackTrace();
       }

       t2.start();

       //Главный поток продолжит работу только после того, How t1 и t2 завершат работу
       try {
           t1.join();
           t2.join();
       } catch (InterruptedException e) {
           e.printStackTrace();
       }

       System.out.println("Все потоки закончor работу, программа завершена");

   }
}
우리는 간단한 클래스를 만들었습니다 ThreadExample. 그 임무는 작업 시작에 대한 메시지를 화면에 표시한 다음 5초 동안 잠들고 마지막에 작업 완료를 알리는 것입니다. 복잡한 것은 없습니다. 주요 로직은 클래스에 포함되어 있습니다 Main. 주석을 보십시오. 이 메소드를 사용하여 join()스레드의 실행 순서를 성공적으로 제어했습니다. 주제의 시작 부분을 기억한다면 스레드 스케줄러가 이 작업을 수행한 것입니다. 그는 자신의 재량에 따라 매번 다르게 출시했습니다. 여기서는 메서드를 사용하여 먼저 스레드가 시작되고 실행되고 t1그 다음 스레드가 실행 t2되고 그 뒤에만 프로그램 실행의 메인 스레드가 실행되도록 보장했습니다. 계속하세요. 실제 프로그램에서는 일부 스레드의 실행을 중단해야 하는 상황에 자주 직면하게 됩니다. 예를 들어 스레드가 실행 중이지만 특정 이벤트나 조건이 충족되기를 기다리고 있습니다. 이런 일이 발생하면 중지됩니다. 와 같은 방법이 있다면 아마도 논리적일 것입니다 stop(). 그러나 모든 것이 그렇게 간단하지는 않습니다. 옛날 옛적에 Thread.stop()Java에는 스레드 작업을 중단할 수 있는 메소드가 실제로 존재했습니다. 그러나 나중에 Java 라이브러리에서 제거되었습니다. Oracle 설명서에서 해당 항목을 찾아보면 deprecated 로 표시되어 있음을 확인할 수 있습니다 . 왜? 추가적인 작업 없이 단순히 흐름을 멈추었기 때문이다. 예를 들어 스레드는 데이터로 작업하고 그 안의 내용을 변경할 수 있습니다. stop()그러다가 그는 일하는 도중 갑자기 기절했습니다 . 그게 전부였습니다. 올바른 종료도, 리소스 해제도, 오류 처리도 없었습니다. 이런 일이 전혀 발생하지 않았습니다. 과장하자면 이 방법은 stop()단순히 경로에 있는 모든 것을 파괴했습니다. 그 작동은 누군가가 컴퓨터를 끄기 위해 소켓에서 플러그를 뽑는 것과 비교할 수 있습니다. 네, 원하는 결과를 얻을 수 있습니다. 그러나 몇 주 안에 컴퓨터가 이에 대해 "감사합니다"라고 말하지 않을 것이라는 것을 모두가 이해합니다. 이러한 이유로 Java에서 스레드를 중단하는 논리가 변경되었으며 이제 특별한 방법이 사용됩니다.interrupt() .

Thread.interrupt() 메서드

스레드에서 메서드를 호출하면 어떻게 되나요 interrupt()? 두 가지 옵션이 있습니다:
  1. 예를 들어, 객체가 그 순간에 대기 상태에 있었다면 대기가 join중단 sleep되고 프로그램은 을 발생시킵니다 InterruptedException.
  2. 그 순간 스레드가 작업 상태에 있었다면 개체의 부울 플래그가 설정됩니다 interrupted.
하지만 우리는 이 플래그의 값에 대해 개체를 확인하고 작업을 올바르게 완료해야 합니다! 이를 위해 클래스 Thread에는 특별한 메소드인 가 있습니다 boolean isInterrupted(). 메인 강의에서 봤던 시계 예제로 다시 돌아가 보겠습니다. 편의상 약간 단순화했습니다.
public class Clock extends Thread {

   public static void main(String[] args) throws InterruptedException {
       Clock clock = new Clock();
       clock.start();

       Thread.sleep(10000);
       clock.interrupt();
   }

   public void run() {
       Thread current = Thread.currentThread();

       while (!current.isInterrupted())
       {
           try {
               Thread.sleep(1000);
           } catch (InterruptedException e) {
               System.out.println("Работа потока была прервана");
               break;
           }
           System.out.println("Tik");
       }
   }
}
우리의 경우 시계는 매초마다 시작되고 똑딱거리기 시작합니다. 10초가 지나면 시계 흐름이 중단됩니다. 이미 알고 있듯이, 우리가 인터럽트하려는 스레드가 대기 상태 중 하나에 있으면 결과는 입니다 InterruptedException. 이러한 유형의 예외는 확인된 예외이므로 쉽게 포착할 수 있으며 프로그램 종료 논리가 실행됩니다. 그것이 우리가 한 일입니다. 결과는 다음과 같습니다: Tik Tik Tik Tik Tik Tik Tik Tik Tik 스레드 작업이 중단되었습니다. 이것으로 클래스의 주요 메서드에 대한 소개를 마칩니다 Thread. 지식을 통합하려면 멀티스레딩에 대한 다음 비디오 강의를 시청하세요.
훌륭한 추가 자료가 될 것입니다! 마지막에는 방법에 대한 개요를 설명한 후 이 과정에서 다음에 진행할 내용을 정확하게 알려줍니다. :) 행운을 빕니다!
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION