问题描述
- 关于java的一个多线程问题,为什么输出的不是一次tom一次李四,是不是在输入判断0,1那里有问题?
-
class Producer//这个是单生产线,单消费问题,一个单生产线有多条路径的问题(最后的效果的输入输出线程轮流执行)
{
public static void main(String[] args)
{
//创建资源
Resource res=new Resource();
//创建线程
input in=new input(res);
output out=new output(res);
//创建线程执行路径
Thread a=new Thread(in);//这里只能有单路径,如果用了多路径就会发生不能一进一出。
Thread b=new Thread(out);
Thread c=new Thread(in);
Thread d=new Thread(out);
//启动线程
a.start();
b.start();
c.start();
d.start();
}
}
class Resource//资源//2.这里要进行代码优化
{
private String name;
private String sex;
private boolean flag=false;
public synchronized void setR(String name/*,String sex*/)//同步函数
{
while(flag)//这里把if换成while是为了让被唤醒的线程能再次进行判断flag,阻止输出还没有执行的同时输入进行了多次执行。但是这样就会出现死锁的情况。
try{this.wait();}catch(InterruptedException e){}
this.name=name;
System.out.println(Thread.currentThread().getName()+name+"..."/*sex*/);
//this.sex=sex;
flag=true;
//notify();//因为这个方法时任意唤醒一个线程,当唤醒笨线程的时候就会出现死锁。
notifyAll();//等待的线程全部被唤醒
}
public synchronized void getR()
{
while(!flag)
try{this.wait();}catch(InterruptedException e){}
System.out.println(Thread.currentThread().getName()+name+"..."/*sex*/);
flag=false;
//notify();
notifyAll();
}
}
class input implements Runnable//输入
{
int i=1;
Resource r;
boolean flag;input(Resource r)
{
this.r=r;
}public void run()
{
while(true)
{
if(i==0)
r.setR("tom");
else
r.setR("李四");
i=(i+1)%2;
/*synchronized (r)
{
if(r.flag)//这条控制语句就是为了实现控制是否等待是否输入
try{r.wait();}catch(InterruptedException e){}//这里的wait方法的意思是:如果输入执行完了就等待输出执行完了被唤醒再进行输入,否则再次输入会覆盖之前的值
show();
r.flag=true;
r.notify();
i=(i+1)%2;
}*/
}
}
//void show()
//{
/*if(i==0)
{
r.name="tom";
r.sex="man";
}
if(i==1)
{
r.name="李四";
r.sex="男";
}*/
//}}
class output implements Runnable//输出
{
Resource r;
boolean flag;
output(Resource r)
{
this.r=r;
}
public void run()
{
while(true)
{
r.getR();
/*synchronized (r){
if(!r.flag)//这条控制语句就是为了实现控制是否等待是否输入
try{r.wait();}catch(InterruptedException e){}
System.out.println(r.name+"..."+r.sex);
r.flag=false;
r.notify();}*/
}
}
}
解决方案
Thread a=new Thread(in);//这里只能有单路径,如果用了多路径就会发生不能一进一出。
Thread b=new Thread(out);
Thread c=new Thread(in);
Thread d=new Thread(out);
这里有2个生产者和2个消费者,2个生产者之间是没有约束的,两个消费者之间也是没有约束的。因此2个生产者set进去的名字就不一定是交替的。可能连续2次是一样的。消费者也一样,2个消费者打印的可能是同一个名字。
这个例子一个生成者一个消费者就没问题。去掉c和d两个线程
解决方案二:
你的代码确实是一进一出啊,输出都是很规律的,感觉你这个没有实现多线程啊,程序控制的太多了,你共用了r对象,然后在设置变量时为了避免死锁用了wait和notifyAll方法,其实已经将多线程设置成单线程了。
解决方案三:
多线程不做同步处理,什么输出顺序都有可能