线程间通信
package com.jiangyi;
/*
多线程间通信:多个线程处理同一资源,但是处理动作却不同。
wait():可以让当前处于等待,这时的线程被临时存储到的线程池中。
notify():唤醒线程池中任意一个等待的线程。
notifyAll():唤醒线程池中所有的等待线程。
这些方法在使用时,必须要定义在同步中,必须被所属同步的锁对象来调用。
*/
//创建一个资源描述。资源中有name sex。用于存储数据。
class Resource
{
String name;
String sex;
//定义标记,用于判断资源中是否有数据。
boolean flag;
}
//需要定义一个输入任务描述。既然是线程任务,必须实现Runnable接口。
class Input implements Runnable
{
private Resource r;
// private Object obj = new Object();
Input(Resource r)
{
this.r = r;
}
//覆盖run方法。
public void run()
{
int x = 0;
while(true)
{
synchronized(r)
{
if(r.flag)
try{r.wait();}catch(Exception e){}
//输入任务中必然要处理资源。要给资源中的name sex赋值。
//需要对象。对象确定吗?不确定,传递进来就哦了。输入任务一创建对象就必须有资源。
//完全可以在构造时明确资源对象。
if(x==0)
{
r.name = "zhangsan";
r.sex = "man";
}
else
{
r.name = "小花";
r.sex = "女女女女女";
}
//赋值后,将标记改为true,说明有值。
r.flag = true;
//唤醒等待的线程。
r.notify();
}
x = (x+1)%2;
}
}
}
//需要定义一个输出任务描述。既然是线程任务,必须实现Runnable接口。
class Output implements Runnable
{
private Resource r;
// private Object obj = new Object();
Output(Resource r)
{
this.r = r;
}
public void run()
{
while(true)
{
synchronized(r)
{
if(!r.flag)//资源中没有数据就等待。
try{r.wait();}catch(Exception e){}
System.out.println(r.name+"...."+r.sex);
//将标记改为false.
r.flag = false;
//唤醒等待的线程。其实就是唤醒了输入线程。
r.notify();
}
}
}
}
class ThreadDemo_Resource
{
public static void main(String[] args)
{
//1,创建资源的对象。
Resource r = new Resource();
//2,创建任务对象。
Input in = new Input(r);
Output out = new Output(r);
//3,创建线程对象。
Thread t1 = new Thread(in);
Thread t2 = new Thread(out);
//4,启动并运行线程。
t1.start();
t2.start();
}
}
思考1:
wait(),notify(),notifyAll(),用来操作线程为什么定义在了Object类中?
1,这些方法存在与同步中。
2,使用这些方法时必须要标识所属的同步的锁。
3,锁可以是任意对象,所以任意对象调用的方法一定定义Object类中。
如果不明确对象直接唤醒 将从所有对象等待的锁中随机唤醒一个 情况就不可
控 同步就会出错
代码优化
package com.jiangyi;
class Resource
{
private String name;
private String sex;
//定义标记,用于判断资源中是否有数据。
private boolean flag;
//对外提供方法访问这些属性。
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();
}
}
//需要定义一个输入任务描述。既然是线程任务,必须实现Runnable接口。
class Input implements Runnable
{
private Resource r;
// private Object obj = new Object();
Input(Resource r)
{
this.r = r;
}
//覆盖run方法。
public void run()
{
int x = 0;
while(true)
{
if(x==0)
{
r.set("zhangsan","man");
}
else
{
r.set("小花","女女女女女");
}
x = (x+1)%2;
}
}
}
//需要定义一个输出任务描述。既然是线程任务,必须实现Runnable接口。
class Output implements Runnable
{
private Resource r;
// private Object obj = new Object();
Output(Resource r)
{
this.r = r;
}
public void run()
{
while(true)
{
r.out();
}
}
}
class ThreadDemo2_Resource
{
public static void main(String[] args)
{
//1,创建资源的对象。
Resource r = new Resource();
//2,创建任务对象。
Input in = new Input(r);
Output out = new Output(r);
//3,创建线程对象。
Thread t1 = new Thread(in);
Thread t2 = new Thread(out);
//4,启动并运行线程。
t1.start();
t2.start();
}
}