데이터 베이스 MySQL 튜토리얼 线程等待和释放的小麻烦(wait/notify)

线程等待和释放的小麻烦(wait/notify)

Jun 07, 2016 pm 05:45 PM
object quot thread

class ThreadA extends Thread{

  //线程同步的公共数据区

  Object oa=null;

  ThreadA(Object o){

  this.oa=o;

  }

  //线程A执行逻辑

  public void run(){

  //线程同步区域,需要申请公共数据的锁

  synchronized(oa){

  System.out.println("ThreadA is running......");

  for(int i=0;i

  System.out.println("   ThreadA value is "+i);

  if(i==50){

  try {

  //当前线程等待

  Thread.currentThread().wait();

  } catch (InterruptedException e) {

  e.printStackTrace();

  }

  }//if(i==50)

  }//for(int i)

  }

  }

  }

  /**

  *  线程B:等待线程A放弃锁,然后获得锁并执行,完成后唤醒线程A

  */

  class ThreadB extends Thread{

  //线程同步的公共数据区

  Object ob=null;

  ThreadB(Object o){

  this.ob=o;

  }

  //线程B执行逻辑

  public void run(){

  //线程同步区域,需要申请公共数据的锁

  synchronized(ob){

  System.out.println("ThreadB is running......");

  for(int i=0;i

  System.out.println("   ThreadB value is "+i);

  }

  

  //唤醒等待的线程

  notify();

  }

  }

  }

  //测试

  public class ThreadTest {

  public static void main(String[] args){

  Object lock=new Object(); //公共数据区

  ThreadA threada=new ThreadA(lock);

  ThreadB threadb=new ThreadB(lock);

  threada.start(); //线程A执行

  threadb.start(); //线程B执行

  }

  }       程序很简单,就是让线程A,B交替打印。但是运行的时候会抛出两个异常:

  Exception in thread "Thread-0" java.lang.IllegalMonitorStateException: current thread not owner

  Exception in thread "Thread-1" java.lang.IllegalMonitorStateException: current thread not owner

  问题就处在ThreadA中的Thread.currentThread().wait(); 和ThreadB中的notify();上。

  初学者理解wait()的时候都认为是将当前线程阻塞,所以Thread.currentThread().wairt();视乎很有道理。但是不知道大家有没有发现,在JDK类库中wait()和notify()方法并不是Thread类的,而是Object()中的。我们仔细看看wait方法的JDK文档:

  public final void wait() throws InterruptedException

  Object (Java 2 Platform SE 6)

  

  在其他线程调用此对象的 notify() 方法或 notifyAll() 方法前,导致当前线程等待。 换句话说,此方法的行为就好像它仅执行 wait(0) 调用一样。

  当前线程必须拥有此 对象监视器 。该线程发布对此监视器的所有权并等待 ,直到其他线程通过调用 notify 方法,或 notifyAll 方法通知在此对象的监视器上等待的线程醒来。 然后该线程将等到重新获得对监视器的所有权后才能继续执行。

  对于某一个参数的版本,实现中断和虚假唤醒是可能的,而且此方法应始终在循环中使用:

  synchronized (obj) {

  while ()

  obj.wait();

  // Perform action appropriate to condition

  }

  此方法只应由作为此对象监视器的所有者的线程来调用。

  抛出: IllegalMonitorStateException - 如果当前线程不是此对象监视器的所有者。

  InterruptedException - 如果在当前线程等待通知之前或者正在等待通知时,任何线程中断了当前线程。在抛出此异常时,当前线程的中断状态 被清除。

  看完JDK文档以后,很显然,只要把开始的程序中Thread.currentThread().wait();改成oa.wait() 。 notify();改成 ob.notify()就没有问题了。

  也就是说,只能通过同步块obj来调用wait/notify方法 ,而不能通过想当然的线程调用这两个方法。至于为什么是这样,我有一种想法,大家可以一起讨论一下:

  首先,我们都知道JVM会给每一个对象都分配唯一的一把锁。这把锁是在对象中的。

  然后,当Thread-0线程获得了这把锁后,应该是在对象中的锁内记录下当前占有自己的线程号,并把自己设置为已被占用。那么当Thread-0需要放弃锁的时候,锁对象会吧 Thread-0放入到锁的等待队列中 。而这一切和Thread-0是没有任何关系的。自然也轮不到Thread-0对象来调用某个方法来改变另一个对象中的锁(这一点也说不通,我自己的锁凭什么让你来改)。

본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.

핫 AI 도구

Undresser.AI Undress

Undresser.AI Undress

사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover

AI Clothes Remover

사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool

Undress AI Tool

무료로 이미지를 벗다

Clothoff.io

Clothoff.io

AI 옷 제거제

AI Hentai Generator

AI Hentai Generator

AI Hentai를 무료로 생성하십시오.

인기 기사

R.E.P.O. 에너지 결정과 그들이하는 일 (노란색 크리스탈)
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 최고의 그래픽 설정
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. 아무도들을 수없는 경우 오디오를 수정하는 방법
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌
WWE 2K25 : Myrise에서 모든 것을 잠금 해제하는 방법
3 몇 주 전 By 尊渡假赌尊渡假赌尊渡假赌

뜨거운 도구

메모장++7.3.1

메모장++7.3.1

사용하기 쉬운 무료 코드 편집기

SublimeText3 중국어 버전

SublimeText3 중국어 버전

중국어 버전, 사용하기 매우 쉽습니다.

스튜디오 13.0.1 보내기

스튜디오 13.0.1 보내기

강력한 PHP 통합 개발 환경

드림위버 CS6

드림위버 CS6

시각적 웹 개발 도구

SublimeText3 Mac 버전

SublimeText3 Mac 버전

신 수준의 코드 편집 소프트웨어(SublimeText3)

Java에서 Runnable과 Thread의 차이점은 무엇입니까? Java에서 Runnable과 Thread의 차이점은 무엇입니까? May 07, 2023 pm 05:19 PM

Java에서 멀티스레딩을 구현하는 방법에는 두 가지가 있습니다. 하나는 Thread 클래스를 상속하는 것이고, 다른 하나는 Runnable 인터페이스를 구현하는 것입니다. Thread 클래스는 java.lang 패키지에 정의되어 있습니다. 클래스가 Thread 클래스를 상속하고 이 클래스의 run() 메서드를 재정의하는 한 다중 스레드 작업을 구현할 수 있습니다. 그러나 클래스는 하나의 상위 클래스만 상속할 수 있으며 이는 이 메서드의 제한 사항입니다. 예를 살펴보겠습니다: packageorg.thread.demo;classMyThreadextendsThread{privateStringname;publicMyThread(Stringname){super();this

php提交表单通过后,弹出的对话框怎样在当前页弹出,该如何解决 php提交表单通过后,弹出的对话框怎样在当前页弹出,该如何解决 Jun 13, 2016 am 10:23 AM

php提交表单通过后,弹出的对话框怎样在当前页弹出php提交表单通过后,弹出的对话框怎样在当前页弹出而不是在空白页弹出?想实现这样的效果:而不是空白页弹出:------解决方案--------------------如果你的验证用PHP在后端,那么就用Ajax;仅供参考:HTML code

Java Object를 바이트로, 바이트를 Object로 변환하는 방법은 무엇입니까? Java Object를 바이트로, 바이트를 Object로 변환하는 방법은 무엇입니까? Apr 20, 2023 am 11:37 AM

Object에서 byte로, byte에서 Object로 오늘은 Object에서 byte로 변환하는 방법과 byte에서 Object로 변환하는 방법을 알아보겠습니다. 먼저 학생 클래스를 정의합니다. packagecom.byteToObject;importjava.io.Serialized;publicclassstudentimplementsSerialized{privateintsid;privateStringname;publicintgetSid(){returnsid;}publicvoidsetSid(in

Java 객체 클래스에서 메소드를 사용하는 방법 Java 객체 클래스에서 메소드를 사용하는 방법 Apr 18, 2023 pm 06:13 PM

1. Object 클래스 소개 Object는 Java에서 기본적으로 제공하는 클래스입니다. Object 클래스를 제외한 Java의 모든 클래스는 상속 관계를 갖습니다. 기본적으로 Object 상위 클래스를 상속합니다. 즉, Object의 참조를 이용하여 모든 클래스의 객체를 받을 수 있습니다. 예: Object를 사용하여 모든 클래스의 객체 수신 classPerson{}classStudent{}publicclassTest{publicstaticvoidmain(String[]args){function(newPerson());function(newStudent());}public

Jul 24, 2023 pm 11:01 PM

Java의 Thread.start() 함수를 사용하여 새 스레드를 시작합니다. Java에서는 멀티스레딩을 사용하여 여러 작업을 동시에 실행할 수 있습니다. Java는 스레드를 생성하고 관리하기 위한 Thread 클래스를 제공합니다. Thread 클래스의 start() 함수는 새 스레드를 시작하고 스레드의 run() 메서드에 있는 코드를 실행하는 데 사용됩니다. 코드 예: publicclassMyThreadextendsThread{@Overr

Thread는 Java에서 인터페이스를 어떻게 생성합니까? Thread는 Java에서 인터페이스를 어떻게 생성합니까? May 17, 2023 pm 12:49 PM

자바에서는 쓰레드에 있어서 쓰레드(Thread)가 필수적이다. 스레드는 프로세스보다 더 가벼운 예약 실행자입니다. 스레드를 사용하는 이유는 무엇입니까? 스레드를 사용하면 운영 체제 프로세스에서 리소스 할당과 실행 일정을 분리할 수 있습니다. 각 스레드는 프로세스 리소스(메모리 주소, 파일 I/O 등)를 공유할 수 있을 뿐만 아니라 독립적으로 예약할 수도 있습니다(스레드는 CPU 예약의 기본 단위입니다). 참고 1. Thread는 Thread를 만드는 데 가장 중요한 클래스이며, 단어 자체도 Thread를 나타냅니다. 2. Thread 클래스는 Runnable 인터페이스를 구현합니다. 인스턴스 publicclassThreadDemoextendsThread{publicvoidrun(){for(inti=0

Java는 객체 클래스의 getClass() 함수를 사용하여 객체의 런타임 클래스를 얻습니다. Java는 객체 클래스의 getClass() 함수를 사용하여 객체의 런타임 클래스를 얻습니다. Jul 24, 2023 am 11:37 AM

Java는 Object 클래스의 getClass() 함수를 사용하여 객체의 런타임 클래스를 얻습니다. Java에서 각 객체에는 객체의 속성과 메서드를 정의하는 클래스가 있습니다. getClass() 함수를 사용하여 객체의 런타임 클래스를 가져올 수 있습니다. getClass() 함수는 Object 클래스의 멤버 함수이므로 모든 Java 객체가 이 함수를 호출할 수 있습니다. 이 기사에서는 getClass() 함수를 사용하는 방법을 소개하고 몇 가지 코드 예제를 제공합니다. get을 사용하세요

Java의 기본 데이터 유형과 객체 간의 관계는 무엇입니까 Java의 기본 데이터 유형과 객체 간의 관계는 무엇입니까 May 01, 2023 pm 04:04 PM

기본 데이터 유형과 Object 사이의 관계 Object가 모든 유형의 기본 클래스라는 것을 누구나 들어봤을 것입니다. 그러나 이 문장은 실제로 정확하지 않습니다. 왜냐하면 Java의 기본 데이터 유형은 Object와 관련이 없기 때문입니다. 예를 들어 swap 메소드를 호출할 때 실제로 Object는 기본 데이터 유형과 아무 관련이 없기 때문에 int 유형을 swap(Objectobj) 메소드에 직접 전달할 수 없습니다. 이제 자동으로 Wrapping하게 되어 Integer 타입이 되었고, 기본 데이터 타입의 래퍼 클래스인 Swap 메소드를 성공적으로 호출할 수 있게 되었습니다.

See all articles