`
yydcj
  • 浏览: 61537 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

奇怪的notify()与notifyAll()的执行问题

阅读更多

摘自http://www.javaworld.com.tw/jute/post/view?bid=5&id=72452&sty=1

 

於 2004-09-28 14:49 user profile send a private message to user reply to post reply to post search all posts by select and copy to clipboard. 
ie only, sorry for netscape users:-) add this post to my favorite list


大家好!我是Java新手!
我發現一個問題捏!

notifyAll()可以通知所有等待它的執行緒,
我測試用notify()的結果也會通知所有的執行緒捏!
請問它們最大的差別在哪呢?

執行環境:j2sdk1.4.2_05 + Eclipse3.0

package concurrent;

class Y extends Thread {
	  int total;
	  public void run() {
	    synchronized(this) {
	      while(total < 50) {
	        try {
	          Thread.sleep(500);
	        } catch(InterruptedException ie) {}
	        total++;
	      }
	      notify();
	    }
	  }
	}
	 
	public class ClassOne implements Runnable {
	  Y ty;
	  
	  ClassOne(Y ty) {
	    this.ty = ty;
	  }
	  
	  public void run() {
	    synchronized(ty) {
	      try {
	        ty.wait();
	      } catch(InterruptedException ie) {}
	      System.out.println(Thread.currentThread().getName() + " Be notify()");
	    }
	  }
	  public static void main(String[] args) {
	    Y ty = new Y();
	    ClassOne x = new ClassOne(ty);
	    
	    Thread t1 = new Thread(x, "t1");
	    Thread t2 = new Thread(x, "t2");
	    Thread t3 = new Thread(x, "t3");
	    t1.start();
	    t2.start();
	    t3.start();
	    ty.start();    
	  }
	}
 

於 2004-10-03 04:52 user profile send a private message to user send email to Duncan reply to post reply to post search all posts by select and copy to clipboard. 
ie only, sorry for netscape users:-) add this post to my favorite list

經過我與其他版主的討論,這可以說是一個 bug 或是說這是一個令人意想不到 side effect(我沒留意到有哪份官方文件有提到這一點)。

原 因在於 Thread object 結束時(成為 dead thread)會(在自己身上)執行 notifyAll method,這一點可以從 Thread - join method 看出來(當一個 thread T1 invoke join(0) or join() 在另一個 thread object T2 身上,T1 thread 會 block 住,直到 thread T2 成為 non-alive thread)。

public final synchronized void join(long millis) 
    throws InterruptedException {
	long base = System.currentTimeMillis();
	long now = 0;

	if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
	}

	if (millis == 0) {
	    while (isAlive()) {
		wait(0);
	    }
	} else {
	    while (isAlive()) {
		long delay = millis - now;
		if (delay <= 0) {
		    break;
		}
		wait(delay);
		now = System.currentTimeMillis() - base;
	    }
	}
    }
 



可以看到 Thread - join method 是以 synchronization 的機制來實做,當 join 的 actual argument value 為 0 是採用 wait(0) 來讓 caller thread block 住,wait(0) 執行後不會因為 timeout 過了而讓 caller thread wake up,可以想見 Thread class 的底層實做一定有在 run method 執行完畢而 Thread object 所啟動的 thread 成為 dead thread 時,有 invoke notifyAll 在 Thread object 身上,以便 wake up 其他因為 join(0) or join() invocation 而 block 住的 thread,否則其他的 thread 便一直停駐在紅色 的那一個 statement 處。

你試著把 Y - run method 中的 notify method call 拿掉,其他的 thread 還是會自動 wake up,在 ty thread 成為 dead thread 之後。

你把 Y instance 以 Thread 包裝起來執行,就可以避開這問題。

public class ClassOne implements Runnable {
    public static void main(String[] args)
    {
        Y ty = new Y();
        // [略] ...
        new Thread(ty).start();
    }
}
 

 

 

分享到:
评论
1 楼 hadesmile 2010-11-29  
确实是个问题,不过一般不这样用,

相关推荐

    Java 同步方式 wait和notify/notifyall

    线程只有被其他线程调用`notify()`或`notifyAll()`后才能重新获得锁并继续执行。 2. **notify()**:这个方法会唤醒在当前对象监视器上等待的一个线程。如果有多个线程在等待,系统会随机选择其中一个线程进行唤醒。...

    如何在Java中正确使用 wait, notify 和 notifyAll

    wait, notify 和 notifyAll,这些在多线程中被经常用到的保留关键字,在实际开发的时候很多时候却并没有被大家重视。本文对这些关键字的使用进行了描述。  在 Java 中可以用 wait、notify 和 notifyAll 来实现...

    Java notify和notifyAll的区别和相同

    Java中的`notify`和`notifyAll`是多线程编程中的关键方法,它们用于线程间的通信,特别是在处理同步机制时。这两个方法都是在`Object`类中定义的,因此可以应用于任何Java对象。 首先,我们需要理解Java的同步机制...

    基于Java多线程notify与notifyall的区别分析

    当其他线程调用该对象的`notify()`或`notifyAll()`方法时,等待的线程会被随机地(对于`notify()`)或全部地(对于`notifyAll()`)唤醒,但并不会立即恢复执行,而是需要重新竞争锁。 `notify()`方法仅唤醒一个正在...

    Java多线程中wait、notify、notifyAll使用详解

    6. notify 和 notifyAll的区别notify方法只唤醒一个等待(对象的)线程并使该线程开始执行,而notifyAll 会唤醒所有等待(对象的)线程。 五、wait、notify、notifyAll方法的使用场景 wait、notify、notifyAll方法...

    【并发编程】 — 线程间的通信wait、notify、notifyAll

    文章目录1 wait、notify、notifyAll简单介绍1.1 使用方法 + 为什么不是Thread类的方法1.2 什么时候加锁、什么时候释放锁?1.3 notify、notifyAll的区别2 两个比较经典的使用案例2.1 案例1 — ABCABC。。。三个线程...

    java notify和notifyAll的对比

    Java中的`notify`和`notifyAll`方法是多线程编程中的重要概念,它们都是`Object`类的方法,用于在同步控制中唤醒等待在特定对象监视器上的线程。理解这两个方法的区别对于编写高效的并发代码至关重要。 首先,`...

    源码—Java多线程5—死锁和wait notify notifyAll

    源码—Java多线程5—死锁和wait notify notifyAll

    Java多线程基础 线程的等待与唤醒(wait、notify、notifyAll)

    Java多线程基础 线程的等待与唤醒(wait、notify、notifyAll) Java多线程基础中的线程等待与唤醒是一种常见的线程协作机制,通过wait()、notify()和notifyAll()方法来实现线程之间的同步和通信。在本节中,我们将...

    Java多线程同步(wait()notify()notifyAll())[文].pdf

    本文将深入探讨Java中的wait()、notify()和notifyAll()方法,以及synchronized关键字和原子操作在多线程环境中的应用。 1. **wait()方法**: - wait()是Object类的一个方法,它的作用是让当前线程暂停执行并释放它...

    Java 中Object的wait() notify() notifyAll()方法使用

    在并发编程中,线程安全是非常重要的,wait()、notify()和notifyAll()方法就是为了解决线程安全问题的。 一、前言 在并发编程中,除了Thread外,对Object对象的wait()和notify()方法也应该深入了解其用法,虽然知识...

    wait()、notify()和notifyAll()方法2---马克-to-win java视频

    wait()、notify()和notifyAll()方法2---马克-to-win java视频

    wait()、notify()和notifyAll()方法1---马克-to-win java视频

    wait()、notify()和notifyAll()方法1---马克-to-win java视频

    Java的wait(), notify()和notifyAll()使用心得

    4. **死锁和饥饿**:虽然`wait()`, `notify()`, `notifyAll()` 提供了线程间的通信,但不当使用可能导致死锁(两个或更多线程互相等待对方释放资源而无法继续执行)或饥饿(某些线程一直无法获取资源而无法执行)的...

    深入理解Wait、Notify和Wait与sleep区别

    3. **notifyAll()**:与`notify()`类似,但它会唤醒所有等待该对象的线程,这些线程都会尝试获取对象锁,最终只有一个成功并继续执行,其他线程仍然会在锁池中等待。 现在我们来看`sleep()`方法,它来自Thread类,...

    wait和notifyAll方法的使用示例

    当其他线程调用同一个对象的 `notify()` 或 `notifyAll()` 方法时,等待线程有机会重新获得锁并继续执行。需要注意的是,调用 `wait()` 方法必须在 `synchronized` 块或方法中进行,否则会抛出 `...

    wait,notify等线程知识.pdf

    只有当其他线程调用同一对象的notify()或notifyAll()方法,并且当前线程重新获得锁后,它才会从等待状态恢复并继续执行。在调用wait()之前,线程必须已经获取了对象的锁,即wait()、notify()和notifyAll()都必须在`...

    主线程去控制子线程wait与notify

    在实际编程中,`wait()`, `notify()`和`notifyAll()`经常结合`while`循环使用,以确保线程在执行时能正确处理各种情况。例如,子线程可能会使用`while(!condition) wait()`来避免“虚假唤醒”问题,即使在没有被唤醒...

    java之wait,notify的用法([ 详解+实例 ])

    wait方法是Object类的一个方法,用于让当前线程进入等待状态,直到其他线程调用notify或notifyAll方法来唤醒它。在wait方法中,当前线程会释放它所占有的锁,并进入等待状态。wait方法可以带有参数,指定等待的时间...

    java中几个notify、wait使用实例

    在Java的多线程编程中,`notify()`与`wait()`是实现线程间通信的重要方法,它们主要用于解决生产者消费者问题、读者写者问题等典型同步问题。这两个方法定义在`Object`类中,因此所有Java对象都可以作为锁来使用。在...

Global site tag (gtag.js) - Google Analytics