`

线程间协作——wait、notify摘要

阅读更多
wait()、notify是定义在Object中的方法,用来控制线程间的协作。

  • wait方法:使持有该对象的线程把该对象的控制权(也就是锁,java api文档中称之为monitor)交出去,然后处于等待状态。
  • notify方法:就会通知某个正在等待这个对象的控制权的线程可以继续运行。


注意:
1.任何一个时刻,对象的锁(monitor)只能被一个线程拥有。
2.无论是执行对象的wait、notify还是notifyAll方法,必须保证当前运行的线程取得了该对象的锁(monitor)。这意味着调用wait、notify必須在synchronized 方法中,否则在运行期一定会抛出java.lang.IllegalMonitorStateException异常。
3.锁(monitor)可以是对象,也可是一个普通变量。线程间的同步协作必须要保证拿到的锁是同一个对象的引用。如果是以一个普通变量(例如一个boolean的flag),则有可能在运行期间被改变值,而导致线程拿到的不是同一把锁,导致不可预料的问题或抛出java.lang.IllegalMonitorStateException异常。

下面以大家所熟知的生产者与消费者问题的代码来说明wait、notify这两个方法的用法。

public class ProducerConsumer {

	public static void main(String[] args) {
		WoTouStack stack = new WoTouStack();
		Producer producer = new Producer(stack);
		Consumer consumer = new Consumer(stack);
		new Thread(producer).start();
		new Thread(consumer).start();
	
	}

}

class WoTou{
	public int id;

	public WoTou(int id) {
		this.id = id;
	}

	@Override
	public String toString() {
		return "wotou " + id;
	}
	
}

/** 
 * 装窝头的容器类 
 * 
 * */
class WoTouStack{
	int pushcount,popcount = 0;  //生产,消费总计
	int size = 10;
	WoTou[] stack = new WoTou[size];
	int index = 0;
	
	/**
	 * 丢进一个窝头, 并使用notify通知消费者线程来消费
	 * 如果容器满了就通知生产线程等待。
	 * @param wt
	 */
	public synchronized void push(WoTou wt){
		stack[index] = wt;
		index++;
		System.out.println("生产了: " + wt);
		pushcount++;
		if(index == size){
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		this.notify();
	}
	
	/**
	 * 拿出一个窝头, 并使用notify通知生产者线程进行生产
	 * 如果容器空了就通知消费线程等待。
	 * @return
	 */
	public synchronized WoTou pop(){
		if(index < 1){
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		this.notify();
		index--;
		popcount++;
		System.out.println("消费了: " + stack[index]);
		return stack[index];
	}
	
}

/** 生产者 **/
class Producer implements Runnable {
	WoTouStack stack = null;
	public Producer(WoTouStack stack){
		this.stack = stack;
	}
	@Override
	public void run() {
		for (int i = 0; i < 20; i++) {
			WoTou wt = new WoTou(i);
			stack.push(wt);
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.out.println("共生产了" + stack.pushcount);
	}
}

/** 消费者 **/
class Consumer implements Runnable {
	WoTouStack stack = null;
	public Consumer(WoTouStack stack){
		this.stack = stack;
	}
	@Override
	public void run() {
		for (int i = 0; i < 20; i++) {
			stack.pop();
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		System.out.println("共消费了" + stack.popcount);
	}
}
分享到:
评论

相关推荐

    第10章 线程.ppt————电子版_ppt版

    【线程间通信】是线程间协调工作的手段,通常通过wait()、notify()、notifyAll()以及 BlockingQueue等工具实现。通信使得线程可以在适当的时候通知其他线程继续执行,从而实现多线程间的协作。 【死锁】是多个线程...

    线程——基本线程的应用和线程调用控件

    - 等待/通知(wait/notify)机制:用于线程间的同步,一个线程等待另一个线程的通知后才能继续执行。 - 条件变量:在特定条件下允许线程等待,条件满足时唤醒。 - 管道(Pipe)和队列:用于线程间的通信,将数据...

    Java多线程的小例子——吃包子

    厨师线程负责制作包子,顾客线程负责吃包子,它们通过某种同步机制(如条件变量或wait/notify)协同工作,确保包子的制作和消费有序进行。这个示例是一个生动的教学工具,能够帮助初学者更好地理解和运用Java的多...

    java多线程案例——未完成

    - `wait()`, `notify()`, `notifyAll()`:在同步块内使用,用于线程间的通信和协作。 - `Lock`和`Condition`:更灵活的锁机制,提供公平锁、非公平锁、读写锁等。 4. **死锁**: 当两个或更多线程互相等待对方...

    经典线程例子——Java线程学习指南

    4. wait(), notify()和notifyAll():在synchronized代码块内使用,用于线程间的通信和协作。 三、线程状态 Java线程有五种状态:新建、运行、阻塞、等待和结束。通过Thread类的getState()方法可以获取当前线程的...

    线程通信安全问题

    在Java编程中,多线程通信是一个至关重要的概念,特别是在并发编程中,它涉及到线程间的协作和数据共享。线程通信安全问题是指在多线程环境下,如何保证多个线程对共享资源进行访问时的正确性和一致性。在这个场景下...

    第13章龟兔赛跑——多线程.ppt

    这个模型体现了线程间的协作和同步。 总结来说,通过学习"第13章龟兔赛跑——多线程",我们可以掌握Java中多线程的基本概念、创建和管理,以及如何利用多线程提高程序效率。理解并熟练应用这些知识对于开发高效、...

    通过多线程编程在Java中发现的并发模式和特性——线程、锁、原子等.zip

    - **wait()与notify()**:在对象锁的保护下,线程可以通过这两个方法进行通信,实现线程间的协作。 - **条件变量(Condition)**:ReentrantLock中提供了条件变量,用于实现更复杂的同步逻辑。 6. **并发工具类**...

    Java线程基础知识

    此外,线程间的协作可以通过wait/notify机制来实现。当一个线程在执行过程中需要等待其他线程完成特定动作时,它可以选择等待,直到被其他线程通知。这种机制使得线程之间能够进行有效协调。 总结来说,Java线程...

    java 多线程交互简单范例

    通过分析和运行这些代码,我们可以更好地理解如何在并发环境中控制线程的执行顺序,避免数据不一致,以及如何有效地设计和实现线程间的协作。对于任何希望提升Java并发编程能力的人来说,这些都是非常宝贵的资源。

    基于Java多线程机制的龟兔赛跑程序.pdf

    在龟兔赛跑程序中,我们将使用wait()和notify()方法来控制线程间的协作。例如,兔线程在“睡觉”时,将调用wait()方法进入等待状态;而当需要兔线程继续赛跑时,则通过龟线程调用notify()方法来唤醒兔线程。 龟兔...

    Java多线程运算集合

    - 是一种经典的线程协作模型,用来解决生产者和消费者之间的数据交换问题。 - 生产者负责生产数据,消费者负责消费数据,两者通过共享缓冲区进行通信。 #### 十、Java线程:并发协作-死锁 - **死锁**: - 发生...

    Java多线程编程

    - **线程间通信**:Java 提供了多种机制来支持线程间的通信,包括`wait()`、`notify()`、`notifyAll()`等方法以及`BlockingQueue`等高级同步队列。这些机制可以用来实现线程间的协作,比如生产者-消费者模式。 - **...

    线程经典案例

    4. 等待/通知机制:通过wait()和notify()方法,可以让线程在特定条件下进入等待状态,等待其他线程的通知再继续执行,以达到线程间的协作。 通过对这两个经典案例的学习,我们可以更好地理解和掌握Java中的线程同步...

    Java多线程与线程安全实践-基于Http协议的断点续传.zip

    Java提供了多种线程同步机制,如`synchronized`关键字、`wait()`, `notify()`和`notifyAll()`方法,以及`Lock`接口和相关的实现类(如`ReentrantLock`)。这些机制用于避免竞态条件和死锁,确保对共享资源的访问有序...

    73道Java面试题合集-多线程与进程

    - `wait()`, `notify()`, `notifyAll()`:在`synchronized`块内使用,用于线程间的协作。 6. **死锁**: - 死锁是两个或更多线程相互等待对方释放资源导致的僵局。 - 避免死锁的方法包括:避免嵌套锁,设置锁的...

    多线程BUFFER例子

    3. 使用`std::condition_variable`实现条件等待,提高线程间的协作效率。 4. 设计并实现生产者-消费者问题,理解其工作原理和解决方法。 通过这个例子,开发者可以学习到如何在实际项目中有效地利用多线程和同步...

    经典线程同步问题(生产者&amp;消费者)--Java实现.doc

    为了解决这两个线程之间的协作问题,Java提供了多种线程同步机制,如synchronized关键字、wait()和notify()方法以及高级的并发工具类。 1. **synchronized关键字**:在Java中,synchronized用于控制多线程对共享...

    JAVA线程第三版

    5. **线程通信**:掌握`wait()`, `notify()`和`notifyAll()`方法,以及`BlockingQueue`等高级工具,实现线程间的通信与协作。 6. **线程池**:学习`ExecutorService`、`ThreadPoolExecutor`和`...

    java 高级java 多线程 代码

    2. **同步机制**:使用`synchronized`关键字、`wait()`, `notify()`或`join()`方法控制线程间的协作。 3. **资源管理**:合理分配线程资源,避免过多线程导致系统资源耗尽。 4. **性能优化**:通过调整线程数量、...

Global site tag (gtag.js) - Google Analytics