java多线程通信问题

我们首先用一个程序来解释多线程的通信。

在该程序中,Storage类中有存储和读取的方法,这样我们建立两个线程来分别利用Storage类中的两个方法,就能达到一个简单的通信.

package cn.itcast.example;
class Test{
	public static void main(String[]args)
	{
		Storage st=new Storage();
		Input input=new Input(st);//两个线程承接一个相同的类进而可以进行多线程的通信
		Output output=new Output(st);
		new Thread(input).start();
		new Thread(output).start();
	}
}
class Storage{ //建立一个用于多线程通信的类
	private int[] cells=new int[10];
	private int inPos,outPos;
	public void put(int num)
	{//建立写入数组元素的方法
		if(inPos>=cells.length)inPos=0;
		cells[inPos]=num;
		System.out.println("在cells数组中["+inPos+"]位置放入元素:"+num);
        inPos++;	
	}
	public void get() {
		if(outPos>=cells.length)outPos=0;
		System.out.println("在cells数组中["+outPos+"]位置取出元素:"+cells[outPos]);
		outPos++;
	}
}
class Input implements Runnable{//建立一个多线程通信的一环,输入信息
    private Storage st;	
    private int num;
    Input(Storage st)
    {
    	this.st=st;
    }
    public void run() {
    	while(true)
    	{
    		st.put(num++);
    		if(num==20)num=0;
    	}
    }
}
class Output implements Runnable{
	private Storage st;
	Output(Storage st)
	{
		this.st=st;
	}
	public void run() {
		while(true)
		{
			st.get();
		}
	}
}

运行结果:

在这里插入图片描述
在这里插入图片描述

我们能看出通过对数组的取用元素两个线程达到了通信。但我们还是能看到一个问题,在数组中放入元素中一定是按照我们既定的顺序的,但从数组中取出元素时,有时是没有按照我们的意愿的;通过分析我们可知,当放入元素的线程运行时(依据多线程运行机制)插入运行了取出元素的线程,但是当再次回到放入线程时,是不会影响到我们放入元素的位置和大小的。相反的,当取出元素线程中插入放入元素线程时,就有可能改变我们当前想要读取的数组,使得取出的元素不连续.

这里我们用同步锁来解决,这里在介绍三个方法

this.wait():使当前线程放弃同步锁并进入等待,直到其他线程进入该同步锁调用了this.notify()或this.notifyAll()方法

this.notify():唤醒此同步锁上等待的第一个调用this.wait()方法的线程

this.notifyAll():唤醒此同步锁上调用this.wait()方法的所有线程

这里我们利用上述方法来解决读取数据的不连续问题,我们来改写Storage类。

package cn.itcast.example;
class Test{
	public static void main(String[]args)
	{
		Storage st=new Storage();
		Input input=new Input(st);//两个线程承接一个相同的类进而可以进行多线程的通信
		Output output=new Output(st);
		new Thread(input).start();
		new Thread(output).start();
	}
}
class Input implements Runnable{//建立一个多线程通信的一环,输入信息
    private Storage st;	
    private int num;
    Input(Storage st)
    {
    	this.st=st;
    }
    public void run() {
    	while(true)
    	{
    		st.put(num++);
    		if(num==20)num=0;
    	}
    }
}
class Output implements Runnable{
	private Storage st;
	Output(Storage st)
	{
		this.st=st;
	}
	public void run() {
		while(true)
		{
			st.get();
		}
	}
}
class Storage{
private int[] cells=new int[10];
private int count;
private int inPos,outPos;
    public synchronized void put(int num)
    {
    	try {
    		while(count==cells.length)
    			this.wait();//当写数据操作到达数组最大范围时,利用this.wait()方法,停止当前线程
    		cells[inPos]=num;
    		System.out.println("在cells["+inPos+"]中放入"+cells[inPos]);
            if(++inPos==cells.length)
            	inPos=0;
            count++;
            this.notify();//这里来唤醒线程
    	}catch(Exception e)
    	{	
    	}
    }
    public synchronized void get() {
    	try {
    		while(count==0)
    			this.wait();
    		System.out.println("在cells["+outPos+"]中取出"+cells[outPos]);
    		if(++outPos==cells.length)
    			outPos=0;
    		count--;
    		this.notify();
    	}catch(Exception e) {	
    	}
    }
}

在这里插入图片描述
在这里插入图片描述

这里我们可以看出取用数据都有顺序了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值