下面是我原来在CSDN论坛上看到的一个贴子,涉及到同步,wait(),notify()等概念的理解,我试着根据原来的一些回复和Think in Java上的相关概念将wait()和notify()这两个方法剖析了一下,欢迎指教.
问题如下:
分析这段程序,并解释一下,着重讲讲synchronized、wait(),notify 谢谢!
class ThreadA
{
public static void main(String[] args)
{
ThreadB b=new ThreadB();
b.start();
System.out.println("b is start....");
synchronized(b)//括号里的b是什么意思,起什么作用?
{
try
{
System.out.println("Waiting for b to complete...");
b.wait();//这一句是什么意思,究竟让谁wait?
System.out.println("Completed.Now back to main thread");
}catch (InterruptedException e){}
}
System.out.println("Total is :"+b.total);
}
}
class ThreadB extends Thread
{
int total;
public void run()
{
synchronized(this)
{
System.out.println("ThreadB is running..");
for (int i=0;i<100;i++ )
{
total +=i;
System.out.println("total is "+total);
}
notify();
}
}
}
要分析这个程序,首先要理解notify()和wait(),为什么在前几天纪录线程的时候没有纪录这两个方法呢,因为这两个方法本来就不属于Thread类,而是属于最底层的object基础类的,也就是说不光是Thread,每个对象都有notify和wait的功能,为什么?因为他们是用来操纵锁的,而每个对象都有锁,锁是每个对象的基础,既然锁是基础的,那么操纵锁的方法当然也是最基础了.
再往下看之前呢,首先最好复习一下Think in Java的14.3.1中第3部分内容:等待和通知,也就是wait()和notify了.
按照Think in Java中的解释:"wait()允许我们将线程置入“睡眠”状态,同时又“积极”地等待条件发生改变.而且只有在一个notify()或notifyAll()发生变化的时候,线程才会被唤醒,并检查条件是否有变."
我们来解释一下这句话.
"wait()允许我们将线程置入“睡眠”状态",也就是说,wait也是让当前线程阻塞的,这一点和sleep或者suspend是相同的.那和sleep,suspend有什么区别呢?
区别在于"(wait)同时又“积极”地等待条件发生改变",这一点很关键,sleep和suspend无法做到.因为我们有时候需要通过同步(synchronized)的帮助来防止线程之间的冲突,而一旦使用同步,就要锁定对象,也就是获取对象锁,其它要使用该对象锁的线程都只能排队等着,等到同步方法或者同步块里的程序全部运行完才有机会.在同步方法和同步块中,无论sleep()还是suspend()都不可能自己被调用的时候解除锁定,他们都霸占着正在使用的对象锁不放.
而wait却可以,它可以让同步方法或者同步块暂时放弃对象锁,而将它暂时让给其它需要对象锁的人(这里应该是程序块,或线程)用,这意味着可在执行wait()期间调用线程对象中的其他同步方法!在其它情况下(sleep啊,suspend啊),这是不可能的.
但是注意我前面说的,只是暂时放弃对象锁,暂时给其它线程使用,我wait所在的线程还是要把这个对象锁收回来的呀.wait什么?就是wait别人用完了还给我啊!
好,那怎么把对象锁收回来呢?
第一种方法,限定借出去的时间.在wait()中设置参数,比如wait(1000),以毫秒为单位,就表明我只借出去1秒中,一秒钟之后,我自动收回.
第二种方法,让借出去的人通知我,他用完了,要还给我了.这时,我马上就收回来.哎,假如我设了1小时之后收回,别人只用了半小时就完了,那怎么办呢?靠!当然用完了就收回了,还管我设的是多长时间啊.
那么别人怎么通知我呢?相信大家都可以想到了,notify(),这就是最后一句话"而且只有在一个notify()或notifyAll()发生变化的时候,线程才会被唤醒"的意思了.
因此,我们可将一个wait()和notify()置入任何同步方法或同步块内部,无论在那个类里是否准备进行涉及线程的处理。而且实际上,我们也只能在同步方法或者同步块里面调用wait()和notify().
这个时候我们来解释上面的程序,简直是易如反掌了.
synchronized(b){...};的意思是定义一个同步块,使用b作为资源锁。b.wait();的意思是临时释放锁,并阻塞当前线程(即这里的主线程,调用b的线程,就像说我想休息一下,让给占有b锁的人执行),好让其他使用同一把锁的线程有机会执行,在这里要用同一把锁的就是b线程本身.这个线程在执行到一定地方后用notify()通知wait的线程,锁已经用完,待notify()所在的同步块运行完之后,wait所在的线程就可以继续执行.
分享到:
相关推荐
### 一个理解wait()与notify()的例子 #### 知识点概述 本文旨在解析一个具体的Java多线程示例代码,以帮助读者更好地理解`wait()`与`notify()`方法的作用及其实现机制。这两个方法是Java中实现线程间通信的重要...
下面是一个简单的生产者消费者模型示例,演示了`wait()`, `notify()` 的使用: ```java public class Buffer { private int data; private boolean available = false; public synchronized void put(int item)...
1. `wait()`: 当一个线程调用某个对象的`wait()`方法时,它会释放该对象的锁,并进入等待状态,直到其他线程调用了该对象的`notify()`或`notifyAll()`方法唤醒它。等待的线程不会自动恢复执行,而是需要重新竞争对象...
下面是一个简单的例子,展示了如何通过 `wait()` 和 `notify()` 控制子线程的执行: ```java public class ThreadControl { private boolean running = false; private Object monitor = new Object(); public ...
接下来,我们通过几个具体的例子来理解这些方法的使用: #### 示例一:线程交替打印数字 在第一个示例中,我们有两个线程`Thread1`和`Thread2`,它们分别打印1-10和11-20之间的数字,但是必须交替进行。为了实现这...
本文将深入探讨`wait`、`notify`以及`notifyAll`这三个关键字的使用及其背后的原理,帮助你理解如何在实际编程中有效地利用它们来解决线程同步问题。 首先,我们需要了解Java中的对象锁。每个Java对象都有一个内置...
在Java编程语言中,`wait()`和`notify()`是Object类中的两个关键方法,它们用于线程间的协作和通信。这两个方法在多线程环境下尤其重要,因为它们允许线程等待特定条件并通知其他线程继续执行。在分析给定的程序之前...
在给定的代码示例中,我们看到了一个模拟家庭共享同一银行账户的场景,通过使用Java多线程的wait()和notify()方法来控制不同线程(代表家庭成员)的操作顺序。这里涉及到的关键知识点包括: 1. **Java多线程**:...
在Java编程语言中,`Monitor`是一个重要的概念,它与多线程同步密切相关。`Monitor`通常是由一个或多个对象锁(synchronized关键字)保护的区域,确保在任何时刻只有一个线程可以访问这部分代码。`wait()`和`pulse()...
`notify()`方法则会随机唤醒一个因调用该对象`wait()`方法而等待的线程,而`notifyAll()`会唤醒所有等待的线程。 在使用`wait()`和`notify()`时,必须确保它们在`synchronized`上下文中调用,这通常是在`...
1. `wait()`: 当一个线程调用对象的`wait()`方法时,它会释放该对象的锁并进入等待状态,直到其他线程调用该对象的`notify()`或`notifyAll()`方法唤醒它。在等待期间,该线程不会消耗CPU资源。 2. `notify()`: 这个...
在这个简单的线程例子中,我们将深入理解线程的概念、如何创建和管理线程,以及它们在多任务处理中的作用。 线程是操作系统分配CPU时间片的基本单位,它们共享同一进程的资源,如内存空间和文件句柄,但拥有独立的...
本文将深入探讨这一主题,基于Java并发编程学习宝典(漫画版)的内容,我们将理解wait和notify的概念,同步的重要性,以及如何正确使用它们。 1. wait/notify 概念 wait()和notify()是Java并发编程中非常重要的两个...
在使用wait/notify机制时,推荐优先使用`notifyAll()`,因为它能保证至少有一个线程可以继续执行,避免死锁和饥饿的情况。同时,为了避免无休止的等待,通常在调用`wait()`之前会使用一个`while`循环检查条件是否...
在Java编程中,线程同步是一种重要的多线程控制机制,用于解决多个线程访问共享资源时可能出现...通过这个例子,我们可以理解Java如何利用同步机制实现多线程环境下的安全通信和协作,这对于开发并发应用程序至关重要。
"Java经典10个例子"通常会涵盖Java语言的核心概念和常用功能,旨在帮助初学者理解并掌握Java编程的关键点。以下是对这十个经典例子可能涉及的知识点的详细解释: 1. ** HelloWorld **:这是每个学习编程语言的人...
5. **多线程**:Java支持多线程编程,例子会介绍Thread类的使用、线程同步方法(如synchronized关键字、wait()、notify()等)以及并发工具类如Semaphore、CountDownLatch等。 6. **网络编程**:Java的Socket编程...
6. **多线程**: 理解线程的创建(Thread类和Runnable接口)、线程同步(synchronized关键字、wait()、notify()、锁对象等)以及并发工具类(如ExecutorService、Future、Callable)。 7. **数据库操作**: JDBC...
例子可能涵盖了如何创建和启动线程,线程同步(如`synchronized`关键字、`wait()`, `notify()`方法)以及线程池的使用。 以上只是部分可能涵盖的Java知识点,实际例子中可能还涉及了更多的主题,如反射、注解、枚举...
在"代码大全的例子"中,你可能会看到如何创建和管理线程,以及如何使用同步机制(如synchronized关键字、wait()、notify()和notifyAll()方法)来避免线程竞态条件。 最后,Java还提供了丰富的标准库,如Swing和...