毕向东java学习日记-----线程通信(1)

线程通信:多个线程操作同一资源。
例子:存数据线程,取数据线程进行通信,放数据-取数据-放-取。。。。。

package threadtest;
class Res
{
String name;
String sex;
	
}
class Input implements Runnable
{
	private Res r;
	private int i=0;
	public Input(Res r)
	{
		this.r=r;
	}
	public void run()
	{
		if(i==0) 
	{
		r.name="mike";
		r.sex="man";
	}
		else
	{
		r.name="lili";
		r.sex="women";
	}
	i=(i+1)%2;
}
}
class Output implements Runnable
{
	private Res r;
	public Output(Res r)
	{
		this.r=r;
	}
	public void run()
	{
		while(true)
		{
			System.out.println(r.name+"......"+r.sex);
		}
	}
}
public class test {
	public static void main(String[] args)
	{
		Res r=new Res();
		Input in=new Input(r);
		Output out=new Output(r);
		Thread a=new Thread(in);
		Thread b=new Thread(out);
		a.start();
		b.start();
	}
}

会出现线程同步问题,考虑两个条件是不是不满足(同一个锁和至少两个线程)
于是思考加同步代码块解决

package threadtest;
class Res
{
String name;
String sex;
	
}
class Input implements Runnable
{
	Object obj=new Object();
	private Res r;
	private int i=0;
	public Input(Res r)
	{
		this.r=r;
	}
	public void run()
	{
	while(true){
	synchronized (obj) {		
	if(i==0) 
	{
		r.name="mike";
		r.sex="man";
	}
		else
	{
		r.name="lili";
		r.sex="women";
	}
}
	i=(i+1)%2;
}
}
}
class Output implements Runnable
{
	private Res r;
	public Output(Res r)
	{
		this.r=r;
	}
	public void run()
	{
		while(true)
		{
			System.out.println(r.name+"......"+r.sex);
		}
	}
}
public class test {
	public static void main(String[] args)
	{
		Res r=new Res();
		Input in=new Input(r);
		Output out=new Output(r);
		Thread a=new Thread(in);
		Thread b=new Thread(out);
		a.start();
		b.start();
	}
}

还是有线程同步问题
原因是没给输出地方加同步代码块,随后又不行,因为锁不是同一个obj,可以用内存中input/output/res的字节码文件当做唯一锁,最好用r这个对象,因为它是唯一的。
顺便再加个信号flag实现输入一次数据,取走后再输入下一个。

package threadtest;
class Res
{
String name;
String sex;
boolean flag=false;//还没有数据
}
class Input implements Runnable
{
//	Object obj=new Object();
	private Res r;
	private int i=0;
	public Input(Res r)
	{
		this.r=r;
	}
	public void run()
	{
	while(true) {
	synchronized (r) {	
	if(r.flag==true) 
		try {
			r.wait();//有数据则不再input而是等待取走
		} catch (Exception e) {
//wait会抛出interrupted异常,因为input实现的runable接口没有抛出异常,所以必须就地try catch。wait还需要有对象监视器即锁,故决定了wait和notify只能放在同步里,放在同步里就需要标明它操作的线程持有的锁。	
		}
	if(i==0) 
	{
		r.name="mike";
		r.sex="man";
	}
		else
	{
		r.name="lili";
		r.sex="women";
	}
	i=(i+1)%2;
	r.flag=true;//放入数据了所以置为true,等待被取走
	r.notify();//唤醒线程池的output线程
}
	}
	}
}

class Output implements Runnable
{
//	Object obj=new Object();//不是同一个锁
	private Res r;
	public Output(Res r)
	{
		this.r=r;
	}
	public void run()
	{
		while(true)
		{
			synchronized (r) {
			if(!r.flag)
				try {
					r.wait();//还没放进去东西,output等待
				} catch (Exception e) {
					
				}
			System.out.println(r.name+"......"+r.sex);//操作同一个对象(访问共享数据),也需要加锁
			r.flag=false;//数据被取走
			r.notify();//通知input线程输入数据
			}
		}
	}
}
public class test {
public static void main(String[] args)
	{
		Res r=new Res();
		Input in=new Input(r);
		Output out=new Output(r);
		Thread a=new Thread(in);
		Thread b=new Thread(out);
		a.start();
		b.start();
	}
}
//锁是任意对象,所以wait等定义在object类下

对代码优化

package threadtest;
class Res
{
private String name;
private String sex;
boolean flag=false;//还没有数据
//对外提供赋值方法和打印方法访问
public synchronized void set(String name,String sex) {
	if(flag)
	try {
		this.wait();
	} catch (Exception e) {
	}
	this.name=name;
	this.sex=sex;
	flag=true;
	this.notify();
 }
public synchronized void out() {
	if(!flag)
		try {
			this.wait();
		} catch (Exception e) {
			
		}
	System.out.println(name+"....."+sex);
	flag=false;
	this.notify();
		
}
}
class Input implements Runnable
{
	private Res r;
	public Input(Res r)
	{
		this.r=r;
	}
	public void run()
	{
		int i=0;
//	while(true) {
//	synchronized (r) {	
//	if(r.flag==true) 
//		try {
//			r.wait();//有数据则不再input而是等待取走
//		} catch (Exception e) {
wait会抛出interrupted异常,因为input实现的runable接口没有抛出异常,所以必须就地try catch。wait还需要有对象监视器即锁,故决定了wait和notify只能放在同步里,放在同步里就需要标明它操作的线程持有的锁。	
//		}
	while(true) {
	if(i==0) 
		r.set("mike","man");
	else
		r.set("lili", "women");
	i=(i+1)%2;
//	r.flag=true;//放入数据了所以置为true,等待被取走
//	r.notify();//唤醒线程池的output线程
//}
	}
	}
}
class Output implements Runnable
{
	private Res r;
	public Output(Res r)
	{
		this.r=r;
	}
	public void run()
	{
		while(true)
		{
			r.out();
//			synchronized (r) {
//			if(!r.flag)
//				try {
//					r.wait();//还没放进去东西,output等待
//				} catch (Exception e) {
//					
//				}
//			System.out.println(r.name+"......"+r.sex);//操作同一个对象(访问共享数据),也需要加锁
//			r.flag=false;//数据被取走
//			r.notify();//通知input线程输入数据
		}
	}
}
class test {
public static void main(String[] args)
	{
		Res r=new Res();
		new Thread(new Input(r)).start();
		new Thread(new Output(r)).start();
//		Input in=new Input(r);
//		Output out=new Output(r);
//		Thread a=new Thread(in);
//		Thread b=new Thread(out);
//		a.start();
//		b.start();
	}
}
//锁是任意对象,所以wait等定义在object类下

不是太懂,感觉有点难,努力进步吧!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值