本文实现的是多生产者与多消费者的问题。如果直接在上篇文章中多加入一个生产者线程和一个消费者线程,则会产生一个生产者生产多个或者一个消费者消费多个的情况,解决办法是将consume和produce函数的最前面的一句if改为while,但是仅仅是这样的话又会产生死锁现象,最终将notify()函数改为notifyall()函数,即每生产或者消费一个后都要将对方线程池的所有线程都唤醒。于是就可以实现多生产者和多消费者同时操作一资源。代码如下:
package threadCommunication;
//生产者和消费者共享的资源
class Resource{
String name;
String sex;
boolean flag=false;
//将生产的环节封装成resource里面,并且封装成同步函数
public synchronized void produce(String name,String sex){
//if(flag){
while(flag){//将if改为while
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//注意:被唤醒后从此执行
this.name=name;
this.sex=sex;
System.out.println("输入:"+name+"性别:"+sex);
this.flag=true;
this.notifyAll();
}
//同理将消费者封装到resource里面,封装成同步函数
public synchronized void consume(){
//if(!flag){
while(!flag){//将if改为while
try {
this.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//注意:被唤醒后从此执行
System.out.println("输出:"+this.name+"性别:"+this.sex);
this.flag=false;
this.notifyAll();
}
}
//输入,代表的是生产者
class Input implements Runnable{
Resource r;
Input(Resource r){
this.r=r;
}
public static int x=1;
public void run() {
while(true){
r.produce("小光"+x, "男");
x++;
if(x>10)
x=1;
}
}
}
//输出,代表的是消费者
class Output implements Runnable{
Resource r;
String name;
Output(Resource r){
this.r=r;
}
public void run() {
while(true){
r.consume();
}
}
}
public class InputOutput3 {
/**
* @param args
*
*/
public static void main(String[] args) {
Resource r=new Resource();
Input in1=new Input(r);
Output out1=new Output(r);
Input in2=new Input(r);
Output out2=new Output(r);
new Thread(in1).start();
new Thread(out1).start();
new Thread(in2).start();
new Thread(out2).start();
}
}
运行结果如下:
注:同步里面活着的县城不知一个,但执行的只有一个,即谁拥有锁谁执行。
wait()释放了锁,其他线程获得了执行的机会,而sleep()不释放锁。
注:while判断标记解决了线程获取执行权后是否要运行的问题。
notify()只唤醒一个线程,如果唤醒了本方,则没有意义,而while+notify()又会导致死锁。
notifyall()解决了本方线程一定会唤醒对方线程的问题。