多线程的等待/通知机制,wait与notify,管道进行线程间通信

本文详细解析了Java中的等待/通知机制,包括wait()和notify()方法的工作原理及应用,对比了wait()与sleep()的区别,notify()与notifyAll()的不同。同时介绍了如何利用管道流(pipeStream)实现线程间的数据传输。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、什么是等待/通知机制

等待/通知机制在生活中比比皆是,比如在就餐时就会出现
厨师和服务员之间的交互要在“菜品传递台”上,在这期间会有几个问题:
1)厨师做完一道菜的时间不确定,所以厨师将菜品放到“菜品传递台”上的时间也是不确定的。
2)服务员取到菜的时间取决于厨师,所以服务员就有“等待(wait)”的状态。
3)服务员如何能取到菜呢?这又的取决于厨师,厨师将菜放在“菜品传递台”上,其实就相当于一种通知(notify),这是服务员才可以拿到菜并交给就餐者。
4)在这个过程中出现了“等待/通知”机制

二、等待/通知机制的实现

        方法 wait()的作用是使当前执行代码的线程进行等待,wait()方法时Object类的方法,该方法用来将当前线程置入“预执行队列”中并且在wait()所在的代码行处停止执行,直到接到通知或被中断为止。在调用wait()之前,线程必须获得该对象的对象级别锁,即只能在同步方法或同步代码块中调用wait()方法。在执行wait()方法后,当前线程释放锁。当被通知后,线程需要和其他线程竞争重新获得锁。如果调用wait()时没有持有适当的锁,则抛出IllegalMonitorStateException,它是RuntimeException 的子类,所以,不需要通过try-catch 语句来进行异常捕获。
        方法 notify() 也要在同步方法或同步代码块中调用,也就是线程在调用前必须获得该对象的对象级别锁。如果调用notify()时没有持有适当的锁,也会抛出IllegalMonitorStateException。该方法用于通知那些可能等待该对象的对象锁的其他线程,如果有多个线程等待,则有线程规划器随机挑选其中一个呈wait()状态的线程,对其发出通知notify,并使他等待获取该对象的对象锁。需要注意的是,在执行了notify()方法后,当前线程不会马上释放该对象锁,呈wait状态的线程也并不能马上获取该对象的锁,要等到执行notify()方法的线程将线程执行完,也就是退出synchronized代码块后,当前线程才会释放锁,而呈wait状态所在的线程才可以获取该对象锁。当第一个获得了该对象锁的wait线程运行完毕以后,它会释放掉该对象锁,此时如果没有再次使用notify语句,则即便该对象已经空闲,其他wait状态等待的线程由于没有得到该对象的通知,还会继续阻塞在wait转态,直到这个对象发出一个notify 或者notifyAll。
        用一句话总结 wait使线程停止运行,而notify使停止的线程继续运行

1. wait() 方法与sleep()方法

wait()方法执行后当前线程会释放锁,而sleep()方法执行后不会释放当前线程的锁。

2.notify() 方法与notifyAll()方法

notify() 方法 每次只能唤醒一个线程,但是唤醒的线程是随机的,所以有可能将与自己是同一类(如生产者)的线程唤醒,造成死锁。

notifyAll()方法 是将所有的处于wait()状态下的线程都给唤醒。

3.wait(long) 方法

带一个参数的wait(long)方法的功能是等待某一时间内是否有线程对锁进行唤醒,如果超过这个时间则自动唤醒。

三、通过管道流进行线程间通讯

在Java语言中提供了各种各样的输入/输出流 Stream,是我们能够很方便地对数据进行操作,其中管道流(pipeStream)是一种特殊的流,用于在不同线程间直接传送数据。一个线程发送数据到输出管道,另一个线程从输入管道中读取数据。通过使用管道,实现不同线程间的通信,而无须借助于类似临时文件之类的东西。

1.字节流

写代码:

import java.io.PipedOutputStream;

public class WriteData {
	
	public void writeMethod(PipedOutputStream out){
		try{
			System.out.println("write :");
			for(int i = 0; i < 300; i++){
				String outData = "" + (i + 1);
				out.write(outData.getBytes());
				System.out.print(outData);
			}
			System.out.println();
			out.close();
		}catch (Exception a){
			
		}
	}

}

读代码:


    import java.io.PipedInputStream;

public class ReadData {
	
	public void readMethod(PipedInputStream input){
		try {
			System.out.println("read :");
			byte[] byteArray = new byte[20];
			int readLength = input.read(byteArray);
			while(readLength !=-1){
				String newData = new String(byteArray,0,readLength);
				System.out.print("jinru");
				System.out.print(newData);
				readLength = input.read(byteArray);
			}
			System.out.println();
			input.close();
		} catch (Exception e) {
			// TODO: handle exception
		}
	}
}

写线程:

import java.io.PipedOutputStream;

public class ThreadWrite extends Thread{
	private WriteData writedata;
	private PipedOutputStream out;
	public ThreadWrite(WriteData writedata,PipedOutputStream out){
		this.writedata = writedata;
		this.out = out;
	}
	@Override
	public void run() {
		super.run();
		writedata.writeMethod(out);
	}
	
}

读线程:

import java.io.PipedInputStream;

public class ThreadRead extends Thread{
	private ReadData readdata;
	private PipedInputStream input;
	public ThreadRead(ReadData readdata,PipedInputStream input){
		super();
		this.readdata = readdata;
		this.input = input;
	}
	@Override
	public void run() {
		super.run();
		readdata.readMethod(input);
	}
}

运行代码:

import java.io.PipedInputStream;
import java.io.PipedOutputStream;

public class Run {
	
	public static void main(String[] args){
		try {
			WriteData writedata = new WriteData();
			ReadData readdata = new ReadData();
			PipedInputStream inputStream = new PipedInputStream();
			PipedOutputStream outStream = new PipedOutputStream();
			outStream.connect(inputStream);
			ThreadWrite threadWrite = new ThreadWrite(writedata, outStream);
			threadWrite.start();
			Thread.sleep(2000);
			ThreadRead threadread = new ThreadRead(readdata, inputStream);
			threadread.start();
		} catch (Exception e) {
			// TODO: handle exception
		}
	}
}

运行结果:(未粘全)
在这里插入图片描述

2.字符流

PipedReader 和 PipedWriter

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值