java多线程-消费者和生产者模式

时间:2021-10-17 07:50:34

/*
* 多线程-消费者和生产者模式
* 在实现消费者生产者模式的时候必须要具备两个前提,一是,必须访问的是一个共享资源,二是必须要有线程锁,且锁的是同一个对象
* */

 /*资源类中定义了name(名字):用来区分消费者还是生产者
* 定义了flag标记:用来区分有没有货物(默认生产一个就要消费一个)
* 定义了count(生产的个数统计)
* set方法:用来生产商品
* out方法:用来消费商品*/
class TestSource{
private String name=null;
private boolean flag=false;
private int count=0;
/*先通过flag标记判断有没有商品,有商品则等待,没有则生产商品,唤醒所有程序,并将flag标记改变*/
public synchronized void set(String name){
//判断是否有产品,这里用while循环,避免在多个生产者同时生产时,会出现生产多个产品,却只消费一个
while(flag){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//生产产品并输出
this.name=name+"编号"+count++;
System.out.println("生产"+name+"++");
//改变标记
flag=true;
//唤醒所有的线程
notifyAll();
}
public synchronized void out(){
while(!flag){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("消费"+name+"---");
flag=false;
notifyAll();
}
}
class Product implements Runnable{
private TestSource ts=null;
//初始化线程里用到的资源
public Product(TestSource ts){
this.ts=ts;
}
//重写线程里run方法
public void run() {
while(true){
ts.set("生产产品");
}
}
}
class Customer implements Runnable{
private TestSource ts=null;
public Customer(TestSource ts){
this.ts=ts;
}
public void run() {
while(true){
ts.out();
}
}
}
public class test {
public static void main(String[] args) {
//初始化唯一的资源
TestSource ts=new TestSource();
//创建生产者和消费者两个对象,并传入两者共同操作的唯一资源
Customer cu=new Customer(ts);
Product pr=new Product(ts);
//将对象传入线程对象
Thread t1=new Thread(cu);
Thread t2=new Thread(pr);
Thread t3=new Thread(cu);
Thread t4=new Thread(pr);
//开启线程
t1.start();
t2.start();
t3.start();
t4.start();
}
}

/*在java1.5版本以后,用lock和unlick代替了synchronized关键字
* 用await()代替了wait()方法
* 用signal()代替了notify()
* 这里的signal可以指定唤醒莫一类的线程,而不是像notifyAll,必须全部唤醒

这里我们对上面的代码进行一定的改写*/

 class TestSource{
private String name=null;
private boolean flag=false;
private int count=0;
//定义lock,用来代替synchronized关键字
private Lock lock=new ReentrantLock();
private Condition condition_pro=lock.newCondition();
private Condition condition_con=lock.newCondition();
public void set(String name){
//对代码段进行上锁
lock.lock();
try {
while(flag){
try {
//wait();
//调用生产者控制方法
condition_pro.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.name=name+"编号"+count++;
System.out.println("生产"+name+"++");
flag=true;
//notifyAll();
//唤醒消费者线程
condition_con.signal();
} finally{
//解锁,让其他进程进入访问
lock.unlock();
} }
public void out(){
lock.lock();
try{
while(!flag){
try {
//wait();
condition_con.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("消费"+name+"---");
flag=false;
//notifyAll();
condition_pro.signal();
}finally{
lock.unlock();
} }
}