`

线程间通信 wait notify

阅读更多
线程间通信


一、通信

线程通信概念:线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体,线程间的通信就成为整体的必用方式之一。当线程存在通信指挥,系统间的交互性会更大,在提高CPU利用率的同事还会使开发人员对线程任务在处理的过程中进行有效的把控与监督。

二、

1.通过 while(true )监听线程
package com.study.current.thread.day02;

import java.util.ArrayList;
import java.util.List;

/**
 * 线程 t1 循环加入元素
 * 线程 t2 监听集合大小,当集合大小为5时,停止线程执行
 * 
 * 当 t2 抛出异常后,但 t1 未停止运行
 *
 */
public class ListAdd1 {

	private volatile static List list = new ArrayList();
	
	public void add (){
		list.add("abcd");
	}
	
	public int size(){
		return list.size();
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {

		final ListAdd1 list1 = new ListAdd1();
		Thread thread1 = new Thread(new Runnable() {
			
			public void run() {
				for(int i = 0 ;i < 10 ; i++){
					list1.add();
					System.out.println(Thread.currentThread().getName() + " list add ");
					try {
						Thread.sleep(500);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		},"t1");
		
		Thread thread2 = new Thread(new Runnable() {
			
			public void run() {
				while(true){
					if(list1.size() == 5){
						System.out.println(Thread.currentThread().getName()+ " stop ");
						throw new RuntimeException();
					}
				}
			}
		},"t2");
		
		thread1.start();
		thread2.start();
	}

}



2.使用 wati notify 优化


package com.study.current.thread.day02;

import java.util.ArrayList;
import java.util.List;

/**
 * 线程 t1 循环加入元素
 * 线程 t2 监听集合大小,当集合大小为5时,停止线程执行
 * 
 * 当 t2 抛出异常后,但 t1 未停止运行
 * 
 * 使用 wait notify 
 *
 * 弊端:非实时性的, t1 一直持有 锁
 */
public class ListAdd2 {

	private volatile static List list = new ArrayList();
	
	public void add (){
		list.add("abcd");
	}
	
	public int size(){
		return list.size();
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {

		final ListAdd2 list1 = new ListAdd2();
		
		final Object lock = new Object();
		
		Thread thread1 = new Thread(new Runnable() {
			
			public void run() {
				synchronized (lock) {
					/**
					 * 2.
					 * t1 线程开始执行
					 * 当 size == 5 是,通知 线程2 ,但 notify 不释放锁
					 * 依然是 t1 持有锁,继续执行,知道 synchronized 中的方法体执行完毕
					 */
					for(int i = 0 ;i < 10 ; i++){
						list1.add();
						System.out.println(Thread.currentThread().getName() + " list add ");
						try {
							Thread.sleep(500);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
						if(list1.size() == 5){
							System.out.println("send message to t2 ");
							lock.notify();
						}
					}
				}
			}
		},"t1");
		
		/**
		 * 1.
		 * t2 线程先启动,监控
		 * 当  list1.size != 5 时 ,wait 释放锁
		 * t1 线程可以执行
		 */
		Thread thread2 = new Thread(new Runnable() {
			
			public void run() {
				/**
				 * 替换 ListAdd1 中的 while 监控
				 */
				synchronized (lock) {
					System.out.println("t2 start ");
					
					if(list1.size() != 5){
						
						try {
							lock.wait();
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
					System.out.println(Thread.currentThread().getName()+ " receive message from t1 ");
					throw new RuntimeException();
				}
				
			}
		},"t2");
		
		thread2.start();
		thread1.start();
	}

}



3.实时性

package com.study.current.thread.day02;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;

/**
 * 线程 t1 循环加入元素
 * 线程 t2 监听集合大小,当集合大小为5时,停止线程执行
 * 
 * 当 t2 抛出异常后,但 t1 未停止运行
 * 
 * 使用 wait notify 
 *
 */
public class ListAdd3 {

	private volatile static List list = new ArrayList();
	
	public void add (){
		list.add("abcd");
	}
	
	public int size(){
		return list.size();
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {

		final ListAdd3 list1 = new ListAdd3();
		
//		final Object lock = new Object();
		// 实时通知
		final CountDownLatch countDownLatch = new CountDownLatch(1);
		Thread thread1 = new Thread(new Runnable() {
			
			public void run() {
//				synchronized (lock) {
					/**
					 * 2.
					 * t1 线程开始执行
					 * 当 size == 5 是,通知 线程2 ,但 notify 不释放锁
					 * 依然是 t1 持有锁,继续执行,知道 synchronized 中的方法体执行完毕
					 */
					for(int i = 0 ;i < 10 ; i++){
						list1.add();
						System.out.println(Thread.currentThread().getName() + " list add ");
						try {
							Thread.sleep(500);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
						if(list1.size() == 5){
							System.out.println("send message to t2 ");
//							lock.notify();
							countDownLatch.countDown();
						}
					}
//				}
			}
		},"t1");
		
		/**
		 * 1.
		 * t2 线程先启动,监控
		 * 当  list1.size != 5 时 ,wait 释放锁
		 * t1 线程可以执行
		 */
		Thread thread2 = new Thread(new Runnable() {
			
			public void run() {
				/**
				 * 替换 ListAdd1 中的 while 监控
				 */
//				synchronized (lock) {
					System.out.println("t2 start ");
					
					if(list1.size() != 5){
						try {
							countDownLatch.await();
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
//						try {
//							lock.wait();
//						} catch (InterruptedException e) {
//							e.printStackTrace();
//						}
					}
					System.out.println(Thread.currentThread().getName()+ " receive message from t1 ");
					throw new RuntimeException();
//				}
				
			}
		},"t2");
		
		thread2.start();
		thread1.start();
	}

}



三、模拟queue

package com.study.current.thread.day02;

import java.util.LinkedList;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 
 * 使用 wait / notify 模拟 Queue 
BlockingQueue:顾名思义,首先它是一个队列,并且支持阻塞的机制,阻塞的放入和得到数据。
put(anObject) 把 anObject 加到 BlockingQueue 里,如果 BlockingQueue 没有空间,则调用此方法的线程被阻断,
直到 BlockingQueue 里面有空间再继续。
take:取走 BlockingQueue 里排在首位的对象,若 BlockingQueue 为空,阻断进入等待状态直到 BlockingQueue 有新的数据被加入
 */
public class MyQueue {
	
	// 定义一个集合
	private final LinkedList<Object> list = new LinkedList<Object>();
	
	// 定义一个计数器,加入list中的元素的数量
	private AtomicInteger count = new AtomicInteger(0);
	
	// 定义集合上下限
	private final int minSize = 0 ;
	private final int maxSize  ; // 创建队列时指定最大长度
	
	// 构造方法,指定集合最大长度
	public MyQueue(int size){
		this.maxSize = size ;
	}
	
	// 定义锁对象
	private Object lock = new Object();
	
	// 放入元素
	public void put(Object anObject){
		synchronized (lock) {
			// 容器已满
			while(maxSize == count.get()){
				try {
					lock.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			// 不满
			list.add(anObject);
			System.out.println("新加入的元素:"+anObject);
			// 集合内元素数量加 1
			count.incrementAndGet();
			// 通知另外一个线程,可以取数据了
			lock.notify();
		}
	}
	
	// 取出元素
	public Object take(){
		Object obj = null ;
		synchronized (lock) {
			// 容器为空
			while(count.get() == minSize){
				try {
					lock.wait();
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			// 不为空
			obj = list.remove();
			System.out.println("取出元素:"+obj);
			// 计数递减
			count.decrementAndGet();
			// 通知另外一个线程
			lock.notify();
		}
		return obj ;
	}
	
	public int getSize(){
		return this.count.get();
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		final MyQueue queue = new MyQueue(5);
		queue.put("a");
		queue.put("b");
		queue.put("c");
		queue.put("d");
		queue.put("e");
		
		System.out.println("当前的容器长度:"+queue.getSize());
	
		Thread t1 = new Thread(new Runnable() {
			// 线程内使用变量,必须用final 修饰
			public void run() {
				queue.put("f");
				queue.put("g");
			}
		});
		try {
			Thread.currentThread();
			Thread.sleep(2000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		
		Thread t2 = new Thread(new Runnable() {
			
			public void run() {
				Object obj = queue.take();
				System.out.println("移除的元素为:"+obj);
				Object obj1 = queue.take();
				System.out.println("移除的元素为:"+obj1);
			}
		});
		
		t1.start();
		t2.start();
	}

}



运行结果:

新加入的元素:a
新加入的元素:b
新加入的元素:c
新加入的元素:d
新加入的元素:e
当前的容器长度:5
取出元素:a
移除的元素为:a
取出元素:b
移除的元素为:b
新加入的元素:f
新加入的元素:g


t1 先运行,插入元素,执行 while ,等待 t2 进行消费
t2 消费完毕,通知 t1 可以插入数据

线程间的通信实现
分享到:
评论

相关推荐

    Java多线程wait和notify

    在Java中,`wait()` 和 `notify()` 方法是实现线程间通信和协作的重要工具,它们属于 `java.lang.Object` 类,这意味着所有类都默认继承了这两个方法。本文将详细探讨如何使用 `wait()` 和 `notify()` 来控制子线程...

    41.线程间的通信-wait与notify-只唤醒一个线程或所有线程.mp4

    在学习Java过程中,自己收集了很多的Java的学习资料,分享给大家,有需要的欢迎下载,希望对大家有用,一起学习,一起进步。

    42.线程间的通信-wait与notify-wait(long)的使用.mp4

    在学习Java过程中,自己收集了很多的Java的学习资料,分享给大家,有需要的欢迎下载,希望对大家有用,一起学习,一起进步。

    浅谈Java线程间通信之wait/notify

    Java线程间通信之wait/notify Java中的wait/notify/notifyAll可用来实现线程间通信,是Object类的方法,这三个方法都是native方法,是平台相关的,常用来实现生产者/消费者模式。 wait()方法将当前线程置于等待...

    39.线程间的通信-wait与notify-wait方法自动释放锁与notify方法不会释放锁.mp4

    在学习Java过程中,自己收集了很多的Java的学习资料,分享给大家,有需要的欢迎下载,希望对大家有用,一起学习,一起进步。

    Java 线程间通信,生产者与消费者模型

    使用wait()和notify()实现的生产者与消费者模型,可以了解如何使用wait()和notify()进行线程间通信。(上一次上传的代码有一个问题没有考虑到,这次修补了——CSDN没法撤销资源,只能再上传了)

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

    在Java多线程编程中,`wait()`和`notify()`是两个非常重要的方法,它们用于线程间的协作和通信。这两个方法是Java语言中的Object类提供的,因此所有的对象都可以使用。在本文中,我们将深入探讨如何使用主线程来控制...

    Java 同步方式 wait和notify/notifyall

    在Java中,`wait()`, `notify()`, 和 `notifyAll()` 是Java Object类的三个方法,它们在实现线程间通信和协作时扮演着关键角色。这些方法主要用于解决线程等待和唤醒的问题,是基于Java Monitor(监视器)模型的。 ...

    wait_notify_demo

    `wait()`、`notify()`和`notifyAll()`是Java中的三个关键字,它们属于Object类的方法,主要用于线程间的通信,尤其在实现生产者消费者模式时发挥着重要作用。本文将深入探讨这些方法以及如何在实际场景中应用它们。 ...

    Java线程间通信的代码示例.zip

    在Java中,线程间通信主要通过共享内存(如共享变量)和消息传递(如wait(), notify(), notifyAll()等方法)来实现。以下是对这些知识点的详细说明: 一、共享内存通信 1. volatile关键字:当多个线程访问同一变量...

    关于Java线程间通信-回调.docx

    此外,Java提供了其他线程间通信机制,如`wait()`, `notify()`, `notifyAll()`,以及`BlockingQueue`等。这些机制通常更适用于复杂的并发场景,比如生产者消费者模型或者线程池。例如,`BlockingQueue`可以使一个...

    一个理解wait()与notify()的例子

    这两个方法是Java中实现线程间通信的重要手段之一,尤其在解决生产者消费者模型、读者写者问题等经典同步问题时非常有用。 #### 代码分析 给出的代码示例包括两个类:`ThreadA`和`ThreadB`。`ThreadA`作为主程序...

    线程的几种控制方式以及线程间的几种通信方式

    4. **线程间通信**:线程间通信允许线程之间交换信息,Java提供了多种机制,如`wait()`, `notify()`, `notifyAll()`,Python中则有`Condition`对象。 5. **线程休眠**:Java的`Thread.sleep()`方法可以让线程暂停...

    android 线程间通讯

    在Android系统中,线程间通信(Inter-Thread Communication,简称ITC)是应用程序开发中的重要环节,尤其在处理耗时操作或者优化UI性能时显得至关重要。线程间通信允许不同线程之间交换数据和执行任务,以确保主线程...

    Java 同步锁 wait notify 学习心得

    Java的`wait`和`notify`方法是实现线程间同步和通信的关键工具。正确使用这些方法可以有效避免线程间的死锁和资源浪费,同时保证多线程程序的正确性和性能。然而,使用这些方法时也需谨慎,不当的使用可能导致线程...

    Java的多线程-线程间的通信.doc

    Java提供了多种机制来实现线程间的通信,包括使用wait(), notify()和notifyAll()方法,以及使用synchronized关键字控制并发访问共享资源。这些方法都定义在java.lang.Thread类中。 1. **wait(), notify()和...

    等待机制与锁机制wait notify

    总结来说,`wait`、`notify`和`notifyAll`是Java多线程中实现线程间通信的关键工具,它们允许线程在适当的时候释放资源并等待,以便其他线程完成特定任务后再继续执行。熟练掌握这些方法的使用,能够帮助你编写出...

    java并发之线程间通信协作.docx

    Java提供了多种线程间通信的机制,其中最常见的两种方式是基于`synchronized`关键字的`Object`类的`wait()`、`notify()`和`notifyAll()`方法,以及使用`ReentrantLock`类的`Condition`接口的`await()`、`signal()`和...

    java中几个notify、wait使用实例

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

Global site tag (gtag.js) - Google Analytics