此程序是用多线程,一个线程控制输入,一个线程控制打印。输入一次,打印一次。
小弟的问题是,为什么我已经加了标志位,并且使用了等待(输入的时候,不允许打印,以防数据出错),但是为什么还是会输入一小会,打印一小会,而不是输入一次打印一次。import java.util.concurrent.locks.*;
class Demo
{
private String name;
private String sex;
private boolean flag=false;
Lock lock=new ReentrantLock();
Condition condition_in=lock.newCondition();
Condition condition_out=lock.newCondition();
public void setMas(String name,String sex)
{
lock.lock();
if(flag)
{
try
{
condition_in.await();
}
catch (InterruptedException e)
{
e.getStackTrace();
}
}
else
{
this.name=name;
this.sex=sex;
flag=true;
condition_out.signal();
}
lock.unlock();
}
public void out()
{
lock.lock();
if (!flag)
{
try
{
condition_out.await();
}
catch (InterruptedException e)
{
e.getStackTrace();
}
}
else
{
System.out.println(this.name+"===="+this.sex);
flag=false;
condition_in.signal();
}
lock.unlock();
}
}
class InputDemo implements Runnable
{
private Demo d;
InputDemo(Demo d)
{
this.d=d;
}
public void run()
{
int num=0;
while (true)
{
if (num==0)
{
d.setMas("MIKE","MAN");
}
else
{
d.setMas("丽丽丽丽","女女女女女女");
}
num=(num+1)%2;
}
}
}
class OutputDemo implements Runnable
{
private Demo d;
OutputDemo(Demo d)
{
this.d=d;
}
public void run()
{
while (true)
{
d.out();
}
}
}
class LockDemo
{
public static void main(String[] args)
{
Demo d=new Demo();
InputDemo id=new InputDemo(d);
OutputDemo od=new OutputDemo(d);
Thread t1=new Thread(id);
Thread t2=new Thread(od);
t1.start();
t2.start(); }
}
小弟的问题是,为什么我已经加了标志位,并且使用了等待(输入的时候,不允许打印,以防数据出错),但是为什么还是会输入一小会,打印一小会,而不是输入一次打印一次。import java.util.concurrent.locks.*;
class Demo
{
private String name;
private String sex;
private boolean flag=false;
Lock lock=new ReentrantLock();
Condition condition_in=lock.newCondition();
Condition condition_out=lock.newCondition();
public void setMas(String name,String sex)
{
lock.lock();
if(flag)
{
try
{
condition_in.await();
}
catch (InterruptedException e)
{
e.getStackTrace();
}
}
else
{
this.name=name;
this.sex=sex;
flag=true;
condition_out.signal();
}
lock.unlock();
}
public void out()
{
lock.lock();
if (!flag)
{
try
{
condition_out.await();
}
catch (InterruptedException e)
{
e.getStackTrace();
}
}
else
{
System.out.println(this.name+"===="+this.sex);
flag=false;
condition_in.signal();
}
lock.unlock();
}
}
class InputDemo implements Runnable
{
private Demo d;
InputDemo(Demo d)
{
this.d=d;
}
public void run()
{
int num=0;
while (true)
{
if (num==0)
{
d.setMas("MIKE","MAN");
}
else
{
d.setMas("丽丽丽丽","女女女女女女");
}
num=(num+1)%2;
}
}
}
class OutputDemo implements Runnable
{
private Demo d;
OutputDemo(Demo d)
{
this.d=d;
}
public void run()
{
while (true)
{
d.out();
}
}
}
class LockDemo
{
public static void main(String[] args)
{
Demo d=new Demo();
InputDemo id=new InputDemo(d);
OutputDemo od=new OutputDemo(d);
Thread t1=new Thread(id);
Thread t2=new Thread(od);
t1.start();
t2.start(); }
}
我这里有个不乱的,话说这个插入源代码怎么用的怎么每次用了都没用的?
public class Test { public static void main(String[] args) {
Share s = new Share();
Producer p = new Producer(s, 1);
Consumer c = new Consumer(s, 1);
p.start();
c.start();
}
}
class Share {
private int contents;
private boolean available = false; public synchronized int get() {
while (available == false) {
try {
wait();
} catch (InterruptedException e) {
}
}
available = false;
notifyAll();
return contents;
}
public synchronized void put(int value) {
while (available == true) {
try {
wait();
} catch (InterruptedException e) {
}
}
available = true;
notifyAll();
contents = value;
}
}
class Producer extends Thread {
private Share shared;
private int number; public Producer(Share s, int number) {
shared = s;
this.number = number;
}
public void run() {
for (int i = 0; i < 10; i++) {
shared.put(i);
System.out.println("生产者" + this.number + " 输出的数据为:" + i);
try {
sleep((int) (Math.random() * 100));
} catch (InterruptedException e) {
}
}
}
}
class Consumer extends Thread {
private Share shared;
private int number; public Consumer(Share s, int number) {
shared = s;
this.number = number;
} public void run() {
int value = 0;
for (int i = 0; i < 10; i++) {
value = shared.get();
System.out.println("消费者" + this.number + " 得到的数据为:" + value);
}
}
}
this.name=name;
this.sex=sex;
flag=true;
condition_out.signal();其实上面的代码就是else后面的执行代码。这段代码有两种情况会执行:
1 flag=false. 直接执行。
2 flag=true 进入等待状态,而从等待退出的时候,name sex 的值都输入好了,flag=true,这时程序应该执行输入操作。同理 要在out()方法的try/catch后加上:
System.out.println(this.name+"===="+this.sex);
flag=false;
condition_in.signal();原理同setMas()一样。
楼主试试看。
把if改成while就可以了
public void setMas(String name,String sex)
{
lock.lock();
//if(flag)
while(flag)
{
try
{
condition_in.await();
}
catch (InterruptedException e)
{
e.getStackTrace();
}
}
//else
//{
this.name=name;
this.sex=sex;
flag=true;
condition_out.signal();
//}
lock.unlock();
}
public void out()
{
lock.lock();
//if (!flag)
while (! flag)
{
try
{
condition_out.await();
}
catch (InterruptedException e)
{
e.getStackTrace();
}
}
//else
//{
System.out.println(this.name+"===="+this.sex);
flag=false;
condition_in.signal();
//}
lock.unlock();
}分析一下一种执行的可能情况LZ就清楚了
假设一开始out线程先执行,然后flag是false,out程进入休眠
然后in线程执行,设置name为mike,sex为man,然后in线程唤醒out线程,此时接下来的执行分2种情况
1 out线程先执行,因为out线程在if块里面,醒来了也不会打印信息,所以out丢失了一次打印信息
2 in线程先执行,因为flag是true,所以in线程等待,in即将设置的参数是name为丽,sex为女,然后out线程执行,发生和1一样的情况,丢失一次打印信息在1的情况下,接下来又分2种可能的执行情况
1-1 out线程先执行,因为flag是ture,所以out打印mike,man,flag为false
1-2 in线程先执行,因为flag是ture,所以in线程等待,in即将设置的参数是name为丽,sex为女在2的情况,因为in线程休眠,所以只有1种执行情况
2-1 out线程执行,打印mike,man,flag为false,唤醒in线程,因为in在if块里面,所以就算醒了也不会设置信息,所以name为丽,sex为女的信息丢失在2-1的情况下,接下来又分2种可能的执行情况
2-1-1 out线程先执行,因为flag是false,所以out线程休眠
2-1-2 in线程先执行,此时in线程设置的参数变为了name为mike,sex为man所以,从2-,2-1,2-1-2的情况来看,就可以知道,name为丽,sex为女的信息丢失,那么out就有可能连着2次输出的都是mike和man,当然线程的随机性还会造成更多的可能,因为线程的假醒,信息设置和打印的丢失,造成无法达到in和out正常交替,所以LZ在写多线程程序的时候,要多注意这一点。