------
Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
在多线程程序中,经常会出现两个线程协同完成任务,这时候就需要线程之间进行通信
在Object类中提供了wait(),notify(),notifyAll()方法用于解决线程间通信的问题,由于java中所有类都是Object的子类,所以任何类的实例对象都可以调用这些方法
方法声明 | 功能描述 |
void wait() | 使当前线程放弃同步锁并进入等待,直到其他线程进入此同步锁,并调用notify()方法, 或者notifyAll()方法唤醒该线程为止 |
void notify() | 唤醒此同步锁上等待的第一个调用wait()方法的线程 |
void notifyAll() | 唤醒此时同步锁上调用wait()方法的所有线程 |
接下来通过调用wait(),notify()方法来实现线程间的通信。
/**
* 多线程通信
* @author Shawn·Zhang
*
*/
public class Example07 {
public static void main(String[] args) {
Storage s = new Storage();//创建数据存储类对象
Input in = new Input(s);//创建Input对象,传入Storage对象
Output out = new Output(s);//创建Output对象,传入Storage对象
new Thread(in).start();//开启新线程
new Thread(out).start();//开启新线程
}
}
class Storage{
private int[] cells = new int[10];//数据存储数组
private int inPos, outPos;//inPos存入时的数组下标,outPos取出时的数组下标
private int count;//存入或者取出数据的数量
public synchronized void put(int num){
try {
while(count==cells.length){//如果放入数据等于cells长度,则次线程等待
this.wait();
}
cells[inPos] = num;//向数组中放入元素
System.out.println("在cells["+inPos+"]中放入数据---"+cells[inPos]);
Thread.sleep(500);//便于观察,增加休眠
inPos++;//存完元素让位置加1
if(inPos==cells.length){
inPos=0;
}
count++;//每放一个元素,count加1
this.notify();
} catch (Exception e) {
e.printStackTrace();
}
}
public synchronized void get(){
try {
while(count==0){//如果count为0,则此线程等待
this.wait();
}
int data = cells[outPos];//从数组中取出元素
System.out.println("从cells["+outPos+"]中取出数据"+data);
Thread.sleep(500);//便于观察,增加休眠
cells[outPos] = 0;//取完后,当前位置的数据为0
outPos++;//取完元素让位置加1
if(outPos==cells.length){
outPos=0;
}
count--;//每取出一个元素,count减1
this.notify();
} catch (Exception e) {
e.printStackTrace();
}
}
}
class Input implements Runnable{//输入线程类
private Storage st;
private int num;//定义一个变量num
Input(Storage st) {//通过构造方法接受一个Storage对象
this.st = st;
}
@Override
public void run() {
while(true){
st.put(num++);//将num存入数组,每次存入后num自增
}
}
}
class Output implements Runnable{//输出线程类
private Storage st;
Output(Storage st) {//通过构造方法接受一个Storage对象
this.st = st;
}
@Override
public void run() {
while(true){
st.get();//循环取出元素
}
}
}
测试结果:
当存入数据的时候,如果count的值和数组cells长度相同时,说明数组已经满了,这时调用wait()方法,使存入数据的线程进入等待状态;
同理,当取出数据时,如果count的值为0,则说明数组已经为空,这时调用wait()方法,使取出数据的线程进入等待状态。
我们可以根据测试结果看出,存入和取出的数据都是依次递增的自然数。