>  기사  >  Java  >  Java 스레드의 6가지 상태와 라이프사이클은 무엇입니까?

Java 스레드의 6가지 상태와 라이프사이클은 무엇입니까?

王林
王林앞으로
2023-05-02 12:07:061418검색

    1. 스레드 상태(라이프 사이클)

    스레드는 특정 시점에 하나의 상태에만 있을 수 있습니다.

    스레드에는 다음 6가지 상태가 있을 수 있습니다.

    • New(새로 생성됨): 시작되지 않은 스레드

    • Runnable(실행 가능): 운영 체제 리소스를 기다려야 하는 실행 가능한 스레드

    • 차단됨: 모니터 잠금을 기다리는 동안 스레드가 차단되었습니다.

    • Waiting: 다른 스레드가 깨어날 때까지 무기한 대기 중: 다른 스레드가 잠금을 수행할 때까지 기다리는 스레드입니다. 지정된 대기 시간 내 작업

    • 종료(terminating): 종료된 스레드입니다.

    • 스레드의 현재 상태를 확인하려면 getState 메소드를 호출하면 됩니다.

    스레드 상태 관계 다이어그램

    참고: 점선 상자의 상태(모두 영어 대문자)는 Java 스레드 상태입니다.

    2. 작업 스레드 상태

    Java 스레드의 6가지 상태와 라이프사이클은 무엇입니까?2.1. 신규 생성 상태(NEW)

    스레드 인스턴스화가 완료된 후 시작되지 않은 스레드의 상태입니다.

    스레드는 세 가지 방법으로 생성할 수 있습니다

    Thread 클래스 run() 메서드 재정의

    • Runnable 인터페이스 구현

    • Callable 인터페이스 구현

    • 간단한 예에 세 가지 방법이 요약되어 있습니다

      public class Demo {
      
          public static void main(String[] args) throws ExecutionException, InterruptedException {
              /**
               * 1.直接重写run() 或继承Thread类再重写run()
               */
              Thread thread = new Thread() {
                  @Override
                  public void run() {
                      System.out.println("Thread");
                  }
              };
              // 开启线程
              thread.start();
      
              /**
               * 2.lambda、内部类或线程类方式实现Runnable接口,实现run()方法
               * 再交给Thread 类
               */
              Thread runThread = new Thread(() -> {
                  System.out.println("Runnable");
              });
              // 开启线程
              runThread.start();
      
              /**
               * 3.lambda、内部类或线程类方式实现Callable接口,实现call()方法
               * 再交给Thread 类:FutureTask本质也是Runnable实现类
               */
              FutureTask<String> futureTask = new FutureTask<String>(() -> {
                  System.out.println("Callable");
                  return "CallableThread";
              });
              Thread callThread = new Thread(futureTask);
              // 开启线程
              callThread.start();
              // 获取call()方法的返回值
              String s = futureTask.get();
              System.out.println("call()方法的返回值:"+s);
          }
      
      }
    • run() 또는 call() 메서드를 재정의하지 않고 Thread 클래스에서 생성된 스레드를 직접 인스턴스화하는 것은 실질적인 의미가 없습니다.

    Callable 메서드에서 생성된 스레드만 스레드의 반환 값을 얻을 수 있습니다.

    2.2.실행 가능 상태(RUNNABLE)

    이 상태는 스레드가 객체를 인스턴스화하고 start() 메서드를 호출한 후 입력되는 상태를 나타냅니다. 스레드는 실행 가능한 상태이며, 프로세서 등의 자원이 있으면 프로그램을 실행할 수 있다.

    이 상태에는

    운영 체제 수준

    의 두 단계인 스레드 준비 및 스레드 실행이 포함되지만, Java 스레드 상태에서는 이 두 단계를 통칭하여 Runnable(실행 가능) 상태라고 합니다.

    스레드가 준비 상태에서 실행 중 상태로 변경될 때 핵심은 스레드가 CPU 리소스를 확보했는지(CPU 타임 슬라이스) 확인하는 것입니다. 이를 확보한 사람은 누구든지 스레드를 실행하고, 확보하지 못하면 기다리세요. . CPU 타임 슬라이스(실행 시간)가 약 10밀리초 정도로 매우 짧기 때문에 스레드 전환 시간도 매우 짧으며, 준비 상태에서 실행 상태로 변경되는 시간도 매우 짧습니다. 개발 변경이므로 Java에서는 이 두 가지를 전체적으로 간주하여 스레드가 실행될 수 있는지 여부에 초점을 맞추고 다른 상태와 구별하여 스레드 개발을 더욱 단순화합니다. 프로그램이 오랜 시간 동안 실행되어야 하고(예: 무한 루프 작성) 실행이 CPU 시간 조각 내에 완료되지 않으면 스레드는 다음 CPU 시간 조각을 확보한 후에야 다음 CPU 시간 조각을 확보해야 합니다. 프로그램을 계속 실행하며, 잡아내지 못한 경우에는 계속해서 프로그램을 실행할 수 있습니다. 그런 다음 스레드에서 프로그램 실행이 완료될 때까지 계속 잡아야 합니다. 사실 이 시나리오는 이전에 본 적이 있을 것입니다. 예를 들어 여러 스레드가 동일한 프로그램을 실행하고 로그를 동일한 파일에 인쇄하면 서로 다른 스레드의 로그가 혼합되어 문제 해결에 도움이 되지 않습니다. 이 문제를 해결하는 일반적인 방법은 첫째, 서로 다른 스레드의 로그를 서로 다른 파일로 인쇄하는 것입니다. 둘째, 로그 정보를 문자열 개체에 저장하고, 프로그램 종료 시 로그 정보를 한꺼번에 파일에 인쇄합니다. 두 번째 방법은 CPU의 시간 조각을 사용하여 로그 정보 인쇄를 완료하는 것입니다.

    참고: 프로그램은 새로 생성된 상태의 스레드에서만 start() 메서드를 호출할 수 있습니다.

    새로 생성되지 않은 상태

    의 스레드에서는 start() 메서드를 호출하지 마세요. 그러면 IllegalThreadStateException 예외가 발생합니다.

    2.3. 차단됨 스레드가

    monitor

    lock

    을 기다리고 있어 차단되었습니다. 한 스레드가 잠금을 획득했지만 해제하지 않았고, 다른 스레드도 잠금을 획득하려고 왔지만 잠금을 획득하지 못해 차단된 상태에 진입했습니다.

    차단 상태는 여러 스레드의 동시 액세스에서만 존재하며 스레드 자체가 "대기 중"으로 진입하여 발생하는 후자의 두 가지 유형의 차단과는 다릅니다. 상태 입력 중

    동기화된 코드 블록/메소드 입력 중

    • 잠금이 획득되지 않음

    • 종료 상태

    모니터 잠금 획득

    • 2.4.wake-up 상태를 기다리는 중입니다. (WAITING)

      전체 프로세스는 다음과 같습니다. 스레드는 먼저 개체의 동기화 메서드에서 개체 잠금을 획득하고 대기 메서드가 실행되면 스레드가 개체 잠금을 해제하고 스레드는 대기 상태에 들어갑니다. 이 객체의 상태 큐; 다른 스레드가 동일한 객체의 잠금을 획득할 때까지 기다린 다음, inform() 또는 informAll() 메서드를 통해 객체 대기 큐에 있는 스레드를 깨웁니다.
    전체 프로세스에서 스레드가 계속 실행되기 전에 wait(), inform() 및 informAll() 메소드가 잠금을 획득해야 한다는 것을 알 수 있으므로 이 세 가지 메소드를 동기화된 코드 블록에 배치해야 합니다. /method 실행, 그렇지 않으면 예외가 보고됩니다: java.lang.IllegalMonitorStateException.

    在同步代码块中,线程进入WAITING 状态时,锁会被释放,不会导致该线程阻塞。反过来想下,如果锁没释放,那其他线程就没办法获取锁,也就没办法唤醒它。

    进入状态

    • object.wait()

    • thread.join()

    • LockSupport.park()

    退出状态

    • object.notify()

    • object.notifyall()

    • LockSupport.unpark()

    2.5.计时等待状态(TIMED_WAITING)

    一般是计时结束就会自动唤醒线程继续执行后面的程序,对于Object.wait(long) 方法还可以主动通知唤醒。

    注意:Thread类下的sleep() 方法可以放在任意地方执行;而wait(long) 方法和wait() 方法一样,需要放在同步代码块/方法中执行,否则报异常:java.lang.IllegalMonitorStateException。

    进入状态

    • Thread.sleep(long)

    • Object.wait(long)

    • Thread.join(long)

    • LockSupport.parkNanos(long)

    • LockSupport.parkNanos(Object blocker, long nanos)

    • LockSupport.parkUntil(long)

    • LockSupport.parkUntil(Object blocker, long deadline)

    注:blocker 参数为负责此线程驻留的同步对象。

    退出状态

    • 计时结束

    • LockSupport.unpark(Thread)

    • object.notify()

    • object.notifyall()

    2.6.终止(TERMINATED)

    线程执行结束

    • run()/call() 执行完成

    • stop()线程

    • 错误或异常>>意外死亡

    stop() 方法已弃用。

    3.查看线程的6种状态

    通过一个简单的例子来查看线程出现的6种状态。

    案例

    public class Demo3 {
        private static Object object ="obj";
        
        public static void main(String[] args) throws InterruptedException {
    
            Thread thread0 = new Thread(() -> {
                try {
                    // 被阻塞状态(BLOCKED)
                    synchronized (object){
                        System.out.println("thread0 进入:等待唤醒状态(WAITING)");
                        object.wait();
                        System.out.println("thread0 被解除完成:等待唤醒状态(WAITING)");
                    }
                    System.out.println("thread0 "+Thread.currentThread().getState());
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
            // 新创建状态(NEW)
            System.out.println(thread0.getName()+":"+thread0.getState());
    
            Thread thread1 = new Thread(() -> {
                try {
                    System.out.println("thread1 进入:计时等待状态(TIMED_WAITING)");
                    Thread.sleep(2);
                    System.out.println("thread1 出来:计时等待状态(TIMED_WAITING)");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                // 被阻塞状态(BLOCKED)
                synchronized (object){
                    System.out.println("thread1 解除:等待唤醒状态(WAITING)");
                    object.notify();
                    System.out.println("thread1 解除完成:等待唤醒状态(WAITING)");
                }
                System.out.println("thread1 "+Thread.currentThread().getState());
            });
            // 新创建状态(NEW)
            System.out.println(thread1.getName()+":"+thread1.getState());
    
            printState(thread0);
            printState(thread1);
    
            // 可运行状态(RUNNABLE)
            thread0.start();
            // 可运行状态(RUNNABLE)
            thread1.start();
    
        }
        
        
        // 使用独立线程来打印线程状态
        private static void printState(Thread thread) {
            new Thread(()->{
                while (true){
                    System.out.println(thread.getName()+":"+thread.getState());
                    if (thread.getState().equals(Thread.State.TERMINATED)){
                        System.out.println(thread.getName()+":"+thread.getState());
                        break;
                    }
                }
            }).start();
        }
    }

    执行结果:简化后的输出结果

    Thread-0:NEW
    Thread-1:NEW
    Thread-0:RUNNABLE
    Thread-1:RUNNABLE
    thread0 进入:等待唤醒状态(WAITING)
    Thread-1:BLOCKED
    thread1 进入:计时等待状态(TIMED_WAITING)
    Thread-0:BLOCKED
    Thread-0:WAITING
    ……
    Thread-0:WAITING
    Thread-1:BLOCKED
    Thread-1:TIMED_WAITING
    ……
    Thread-1:TIMED_WAITING
    Thread-1:BLOCKED
    ……
    Thread-1:BLOCKED
    Thread-0:WAITING
    ……
    Thread-0:WAITING
    thread1 出来:计时等待状态(TIMED_WAITING)
    Thread-0:WAITING
    Thread-1:BLOCKED
    thread1 解除:等待唤醒状态(WAITING)
    Thread-1:BLOCKED
    Thread-0:WAITING
    Thread-0:BLOCKED
    thread1 解除完成:等待唤醒状态(WAITING)
    Thread-1:BLOCKED
    thread1 RUNNABLE
    Thread-0:BLOCKED
    Thread-1:TERMINATED
    thread0 被解除完成:等待唤醒状态(WAITING)
    Thread-0:BLOCKED
    thread0 RUNNABLE
    Thread-0:TERMINATED

    Java 스레드의 6가지 상태와 라이프사이클은 무엇입니까?

    最终的执行结果如图。

    注意:因为案例中使用了独立线程来打印不同线程的状态,会出现状态打印稍微延迟的情况。

    위 내용은 Java 스레드의 6가지 상태와 라이프사이클은 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

    성명:
    이 기사는 yisu.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제