> Java > java지도 시간 > 본문

Java에서 wait() 및 inform() 메서드를 사용하여 공유 리소스의 인스턴스를 작동하는 방법

黄舟
풀어 주다: 2017-10-11 09:52:41
원래의
1365명이 탐색했습니다.

이 글에서는 주로 Java가 wait() inform() 메소드를 사용하여 공유 리소스를 작동하는 방법을 자세히 소개합니다. 이는 특정 참조 값을 가지고 있습니다. 관심 있는 친구는 이를 참조할 수 있습니다.

Java 다중 스레드 공유 리소스

 1 ) ), inform() 및 informAll() 메서드는 로컬 메서드이며 최종 메서드이므로 재정의할 수 없습니다.

 2) 객체의 wait() 메소드 호출은 현재 스레드를 차단할 수 있으며, 현재 스레드는 이 객체의 모니터(예: 잠금 또는 모니터)를 소유해야 합니다.

 3) 객체의 inform() 메소드 호출 이 객체의 모니터를 기다리고 있는 스레드를 깨울 수 있습니다. 이 객체의 모니터를 기다리는 스레드가 여러 개인 경우 그 중 하나만 깨울 수 있습니다.

  4) informAll() 메서드를 호출하면 깨어날 수 있습니다. 이 개체를 기다리는 모든 스레드입니다.

Java에는 PV 작업, 프로세스 상호 배제 등과 관련된 메서드가 없습니다. Java의 동기화() 메소드는 운영 체제 개념의 상호 배타적 메모리 블록과 유사하다는 점에 유의해야 합니다. Java의 Object 클래스 객체에는 For memory locks가 있습니다. 스레드가 메모리 잠금을 획득하면 다른 스레드는 메모리에 액세스할 수 없으므로 Java에서 간단한 동기화 및 상호 배제 작업이 구현됩니다. 이 원리를 이해하면 동기화(this)와 동기화(정적)의 차이점을 이해할 수 있습니다. 상호 배타적 연산이며 정적 멤버는 클래스에 독점적이며 해당 메모리 공간은 클래스의 모든 멤버가 공유합니다. 이로 인해 동기화( ) 정적 멤버를 잠그는 것입니다. 이는 클래스를 잠그는 것과 같습니다. 즉, 상호 배제를 구현하려면 하나의 스레드만 이 클래스의 인스턴스에 동시에 액세스할 수 있습니다. 스레드 간에 서로 깨워야 하는 경우에는 Object 클래스의 wait() 메서드와 nofity() 메서드를 사용해야 합니다.

너무 많이 이야기하고 나면 이해하지 못할 수도 있으므로 멀티 스레딩을 사용하여 연속 1,2,1,2,1,2,1,2,1,2 출력을 달성하는 예를 사용하여 문제를 설명하겠습니다. .


package com.study.thread;
/**
 * 多线程
 * @ClassName: PrintFile 
 * @date 2017年10月10日 下午4:05:04
 */
public class PrintFile implements Runnable{
  //当前线程id
  private int id ;
  //共享资源
  public byte[] res ;
  
  //如果类里写了有参构造器,而任然想保留无参数构造方法,则必须显式的写出该方法。
  public PrintFile() {
    super();
//    System.out.println("我是构造器"); 
  }

  public PrintFile(int id, byte[] res) {
    //构造器中使用super()/this(),必须放在第一行。
    this(); 
    this.id = id;
    this.res = res;
  }

  //静态计数器
  public static int count = 5;
  
  @Override
  public void run() {
    synchronized (res) {
      while(count-->=0){
        try {
          res.notify();//唤醒其他线程中的某一个(唤醒等待res的其他线程,当前线程执行完后要释放锁)
          System.out.println("当前线程id值:"+id);
          
          res.wait();//当前线程阻塞,等待被唤醒
          System.out.println("现在执行的线程是"+Thread.currentThread().getName()+",--wait()后的代码继续执行:"+id);
          
        } catch (InterruptedException e) {
          e.printStackTrace();
        }
      }
      return; 
    }
  }
}
로그인 후 복사

Test:


package com.study.thread;

public class PrintFileTest {
 public static void main(String[] args) {
  byte[] res = new byte[]{0,1,2};//共享资源
  PrintFile p1 = new PrintFile(1, res);
  PrintFile p2 = new PrintFile(2, res);
  
  Thread t1 = new Thread(p1, "a");
  Thread t2 = new Thread(p2, "b");
    
  t1.start();
  t2.start();
 }
}
로그인 후 복사

Result:

현재 스레드 ID 값: 1
현재 스레드 ID 값: 2
지금 실행 중인 스레드는 a이고, --wait() 이후의 코드는 계속됩니다. 실행: 1
현재 스레드 ID 값: 1
현재 실행 중인 스레드는 b이고 --wait() 이후의 코드는 계속 실행됩니다. 2
현재 스레드 ID 값: 2
현재 실행 중인 스레드는 a, 이후의 코드 --wait() 계속 실행되는 코드: 1
현재 스레드 id 값: 1
현재 실행 중인 스레드는 b, --wait() --wait() 이후의 코드 실행 계속: 2
현재 스레드 id 값 : 2
현재 실행 중인 스레드는 --wait () 이후의 코드는 계속 실행됩니다. 1

다음은 이러한 결과가 발생하는 이유를 설명합니다.

먼저 스레드 1과 2가 시작되었다고 가정합니다. 1 먼저 run 메소드를 실행하여 리소스를 얻습니다(실제로는 확실하지 않습니다). 객체 a의 잠금을 획득하고 while 루프에 들어갑니다(여러 라운드의 출력을 제어하는 ​​데 사용됨).

1 이때 객체는 wake를 호출합니다. -up 메서드는 동기화 블록이 실행된 후 잠금을 해제하고 리소스를 기다리는 스레드에 전달함을 의미합니다.

3. wait 메서드는 이 순간부터 객체 잠금을 소유한 스레드(즉, 여기서는 1번 스레드)가 CPU 제어를 해제한다는 의미입니다. 잠금이 해제되고 스레드는 일시적으로 차단 상태에 진입합니다. 동기화 블록이 실행되지 않았기 때문에 1은 아무런 효과가 없습니다.

4. 이전 어느 시점에서 스레드 2는 실행 메서드를 실행했지만 개체 a의 잠금을 얻지 못하여 계속 실행할 수 없습니다. , 그러나 3단계 후에는 a의 잠금을 획득합니다. 이때 a의 wake-up 메소드 inform()을 실행합니다. 마찬가지로 동기화 블록이 실행된 후 잠금을 해제한다는 의미입니다.

5. 출력 2

6. a의 대기 메소드를 실행합니다. 이는 이 순간부터 객체 잠금을 소유하고 있음을 의미합니다. 여기서 2번 쓰레드)는 CPU 제어 권한을 해제하고, 락이 해제되어 블로킹 상태가 됩니다. 다음 코드는 동기화 블록이 실행되지 않았기 때문에 일시적으로 실행되지 않습니다. 2번 스레드가 작동하지 않습니다.

7 이때 1번 스레드가 실행됩니다. 3단계에서 개체 잠금이 사용되지 않는 것으로 확인되므로 3번의 wait 메서드 이후의 코드가 계속 실행됩니다. ------스레드 1이 잠금을 획득하고 wait() 이후의 코드가 계속 실행됩니다. 1;

8. 이때 while 루프는 조건을 충족하고 계속 실행됩니다. 따라서 스레드 1번의 웨이크업 메서드를 실행합니다. 이는 동기화 블록이 실행된 후 잠금을 해제한다는 의미입니다.

9. 대기 메서드를 실행하고 스레드 1을 해제합니다.

11 이때 스레드 2는 다시 잠금을 획득하고 6단계를 실행하며 wait 메서드 이후에 코드를 계속 실행하므로 출력은 다음과 같습니다. ------스레드 2가 잠금을 획득합니다. , 잠깐 () 이후의 코드는 계속 실행됩니다: 2; 그러나 이 두 가지 방법은 프로그램에도 문제가 있습니다. while 루프가 조건을 충족하지 않으면 여전히 리소스를 기다리는 스레드가 있으므로 메인 스레드는 절대 종료되지 않습니다. 물론, 이 프로그램의 목적은 단지 이 두 가지 방법을 사용하는 방법을 보여주는 것입니다.

요약:

wait() 메소드와 통지()는 동기화(리소스)와 함께 사용해야 합니다. 즉, wait 및 inform은 리소스 잠금을 획득한 스레드에서 작동합니다. 구문 관점에서 Obj.wait() 및 Obj.notify는synchronous(Obj){...} 문 블록 내에 있어야 합니다. 기능적으로 말하면, 객체 잠금을 획득한 후 wait() 스레드는 CPU 제어 및 객체 잠금을 적극적으로 해제하는 동시에 이 스레드는 절전 모드로 전환됩니다. 다른 스레드가 해당 스레드를 깨우기 위해 객체의 inform()을 호출할 때까지 계속해서 객체 잠금을 획득하고 실행을 계속할 수 있습니다. 해당 inform()은 객체 잠금 해제 작업입니다. [따라서 우리는 wait 및 inform 메서드 모두 객체의 잠금을 해제할 수 있지만 wait도 CPU 제어를 해제한다는 것을 알 수 있습니다. 즉, 그 뒤에 있는 코드는 실행을 중지하고 스레드는 차단 상태에 들어가는 반면 통지 메서드는 해제되지 않습니다. CPU는 즉시 제어하지만, 해당 동기화(){} 문 블록의 실행이 끝난 후 잠금이 자동으로 해제됩니다. 】잠금을 해제한 후 JVM은 리소스를 기다리는 스레드 중에서 스레드를 선택하고 개체 잠금을 부여한 후 스레드를 깨우고 실행을 계속합니다. 이는 스레드 간의 동기화 및 깨우기 작업을 제공합니다. Thread.sleep()과 Object.wait()는 모두 현재 스레드를 일시 중단하고 CPU 제어를 해제할 수 있습니다. 주요 차이점은 Object.wait()가 동기화 블록 The Thread에 있는 동안 CPU를 해제하는 동안 개체 잠금 제어를 해제한다는 것입니다. sleep() 메서드는 잠금을 해제하지 않고 CPU 제어만 해제합니다.

위 내용은 Java에서 wait() 및 inform() 메서드를 사용하여 공유 리소스의 인스턴스를 작동하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿