线程间通讯学习【五】

[color=red]线程间通讯,当有多个生产者、消费者时,容易导致的问题。[/color]


一、当只有两个线程,一个生产、一个消费的时候,数据是没有问题的,如下:
package com.zzl.thread;

class MyResource{
private String name;
private int number = 1;
private boolean flag = false;

public synchronized void set(String name){
if(flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.name = name +"......"+ number++;
System.out.println(Thread.currentThread().getName()+"...生产者..."+this.name);
this.flag = true;
this.notify();
}

public synchronized void print(){
if(!flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+"---------消费者---------"+this.name);
this.flag = false;
this.notify();
}

}

class Producer implements Runnable{
private MyResource r;
public Producer(MyResource r){
this.r = r;
}
@Override
public void run() {
while(true){
r.set("苹果");
}

}

}

class Consumer implements Runnable{
private MyResource r;
public Consumer(MyResource r){
this.r = r;
}
@Override
public void run() {
while(true){
r.print();
}
}

}


public class ProducerConsumerDemo {

public static void main(String[] args) {
MyResource r = new MyResource();
Producer p = new Producer(r);
Consumer c = new Consumer(r);
Thread t1 = new Thread(p);
Thread t2 = new Thread(c);
t1.start();
t2.start();
}

}

运行效果:
Thread-1---------消费者---------苹果......40535
Thread-0...生产者...苹果......40536
Thread-1---------消费者---------苹果......40536
Thread-0...生产者...苹果......40537
Thread-1---------消费者---------苹果......40537
Thread-0...生产者...苹果......40538
Thread-1---------消费者---------苹果......40538
Thread-0...生产者...苹果......40539
Thread-1---------消费者---------苹果......40539
Thread-0...生产者...苹果......40540
Thread-1---------消费者---------苹果......40540
Thread-0...生产者...苹果......40541
Thread-1---------消费者---------苹果......40541
Thread-0...生产者...苹果......40542
Thread-1---------消费者---------苹果......40542
Thread-0...生产者...苹果......40543
Thread-1---------消费者---------苹果......40543
Thread-0...生产者...苹果......40544
Thread-1---------消费者---------苹果......40544



二、当有两个生产者、消费者时,数据出现了问题:
package com.zzl.thread;

class MyResource{
private String name;
private int number = 1;
private boolean flag = false;

public synchronized void set(String name){
if(flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.name = name +"......"+ number++;
System.out.println(Thread.currentThread().getName()+"...生产者..."+this.name);
this.flag = true;
this.notify();
}

public synchronized void print(){
if(!flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+"---------消费者---------"+this.name);
this.flag = false;
this.notify();
}

}

class Producer implements Runnable{
private MyResource r;
public Producer(MyResource r){
this.r = r;
}
@Override
public void run() {
while(true){
r.set("苹果");
}

}

}

class Consumer implements Runnable{
private MyResource r;
public Consumer(MyResource r){
this.r = r;
}
@Override
public void run() {
while(true){
r.print();
}
}

}


public class ProducerConsumerDemo {

public static void main(String[] args) {
MyResource r = new MyResource();
Producer p = new Producer(r);
Consumer c = new Consumer(r);
Thread t1 = new Thread(p);
Thread t2 = new Thread(p);
Thread t3 = new Thread(c);
Thread t4 = new Thread(c);
t1.start();
t2.start();
t3.start();
t4.start();
}

}

运行效果(第五行、第六行都为生产者):
Thread-0...生产者...苹果......19803
Thread-2---------消费者---------苹果......19803
Thread-0...生产者...苹果......19804
Thread-2---------消费者---------苹果......19804
Thread-0...生产者...苹果......19805
Thread-1...生产者...苹果......19806
Thread-3---------消费者---------苹果......19806
Thread-1...生产者...苹果......19807
Thread-3---------消费者---------苹果......19807
Thread-1...生产者...苹果......19808
Thread-3---------消费者---------苹果......19808
Thread-1...生产者...苹果......19809
Thread-3---------消费者---------苹果......19809



三、如果为多个生产者和消费者,修改如下: if判断改为while判断,当线程被唤醒的时候,都要去判断一下flag; 并把notify 改为notifyAll唤醒线程,不管生产者还是消费者都唤醒。
package com.zzl.thread;

class MyResource{
private String name;
private int number = 1;
private boolean flag = false;

public synchronized void set(String name){
while(flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.name = name +"......"+ number++;
System.out.println(Thread.currentThread().getName()+"...生产者..."+this.name);
this.flag = true;
this.notifyAll();
}

public synchronized void print(){
while(!flag){
try {
this.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName()+"---------消费者---------"+this.name);
this.flag = false;
this.notifyAll();
}

}

class Producer implements Runnable{
private MyResource r;
public Producer(MyResource r){
this.r = r;
}
@Override
public void run() {
while(true){
r.set("苹果");
}

}

}

class Consumer implements Runnable{
private MyResource r;
public Consumer(MyResource r){
this.r = r;
}
@Override
public void run() {
while(true){
r.print();
}
}

}


public class ProducerConsumerDemo {

public static void main(String[] args) {
MyResource r = new MyResource();
Producer p = new Producer(r);
Consumer c = new Consumer(r);
Thread t1 = new Thread(p);
Thread t2 = new Thread(p);
Thread t3 = new Thread(c);
Thread t4 = new Thread(c);
t1.start();
t2.start();
t3.start();
t4.start();
}

}

运行效果:
Thread-0...生产者...苹果......20549
Thread-2---------消费者---------苹果......20549
Thread-1...生产者...苹果......20550
Thread-3---------消费者---------苹果......20550
Thread-0...生产者...苹果......20551
Thread-2---------消费者---------苹果......20551
Thread-1...生产者...苹果......20552
Thread-3---------消费者---------苹果......20552
Thread-0...生产者...苹果......20553
Thread-2---------消费者---------苹果......20553
Thread-1...生产者...苹果......20554
Thread-3---------消费者---------苹果......20554
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值