线程通信:多个线程操作同一资源。
例子:存数据线程,取数据线程进行通信,放数据-取数据-放-取。。。。。
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类下
不是太懂,感觉有点难,努力进步吧!