多线程问题之多生产者/多消费者

本文探讨了多线程环境下生产者与消费者模型的实现,重点介绍了如何利用Java的锁和条件变量来解决同步问题,避免数据错误和死锁的发生。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

多线程问题之多生产者/多消费者 ##

package producer_consumer;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/*
 * 生产者,消费者
 * 多生产者,多消费者
 * 1·if判断标记,只有一次,会导致不该运行的线程运行了,出现数据错误的情况
 * 2·while判断标记解决了线程获取执行权后是否要运行
 * 3·notify只能唤醒一个线程,如果唤醒了本方线程没有意义,而且notify+while会导致死锁
 * 4·notifyAll解决了本方线程有可能会唤醒本方另一线程并执行的问题
 * (唤醒全部线程,本方线程经过判断会进入等待状态,只有对方线程会继续执行)
 * */
class Resource
{
    private String name;
    private int count = 1;
    private boolean flag = false;

    //创建一个锁对象
    Lock lock = new ReentrantLock();

    //通过已有的锁获取该锁上的监视器对象
    //Condition con = lock.newCondition();

    //通过已有的锁获取两组监视器,一组监视生产者,一组监视消费者
    Condition producer_con = lock.newCondition();
    Condition consumer_con = lock.newCondition();

    //以下为使用synchronized实现锁功能
    /*public synchronized void set(String name)
    {
        //if(flag)第一个版本,会出现代码末尾描述的问题一
        while(flag)//将if改为while是需要某线程在被唤醒后再次判断flag,适用于以下的lock
            try
            {
                this.wait();
            } catch (InterruptedException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        this.name = name + count;
        count++;
        System.out.println(Thread.currentThread().getName()+"...生产..."+this.name);
        flag = true;
        //notify();有可能唤醒本方线程并执行,适用于以下的lock中的signal()
        notifyAll();
    }*/
    //优化版
    public void set(String name)
    {
        lock.lock();
        try
        {
            while(flag)//用while比较安全,每次被唤醒都判断一次,以防数据出错
                try
                {
                    producer_con.await();
                } catch (InterruptedException e)
                {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            this.name = name + count;
            count++;
            System.out.println(Thread.currentThread().getName()+"...生产..5.0."+this.name);
            flag = true;
            Thread.sleep(10);
            consumer_con.signal();
        } catch (Exception e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        finally
        {
            lock.unlock();
        }
    }
    /*public synchronized void out()
    {
        while(!flag)
            try
            {
                this.wait();
            } catch (InterruptedException e)
            {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        System.out.println(Thread.currentThread().getName()+"消费........."+this.name);
        flag = false;
        //notify();有可能唤醒本方线程并执行
        notifyAll();
    }*/
    public void out()
    {
        lock.lock();
        try
        {
            while(!flag)
                try
                {
                    consumer_con.await();
                } catch (InterruptedException e)
                {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            System.out.println(Thread.currentThread().getName()+"消费........5.0........"+this.name);
            flag = false;
            Thread.sleep(10);
            producer_con.signal();
        } catch (Exception e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        finally
        {
            lock.unlock();
        }
    }
}
class Producer implements Runnable
{
    private Resource r;
    Producer(Resource r)
    {
        this.r = r;
    }
    @Override
    public void run()
    {
        while(true)
        {
            r.set("烤鸭");
        }
    }

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

}
public class ProducerConsumer
{

    public static void main(String[] args)
    {
        Resource r = new Resource();
        Producer pro = new Producer(r);
        Consumer con = new Consumer(r);
        Thread t0 = new Thread(pro);
        Thread t1 = new Thread(pro);
        Thread t2 = new Thread(con);
        Thread t3 = new Thread(con);
        t0.start();
        t1.start();
        t2.start();
        t3.start();
    }

}
/*
 * 多生产者消费者问题一
 * 1·产生原因:在某个时刻只有t0处于唤醒状态,当该线程执行到notify()时,恰好被唤醒的是
 * 生产者t1线程,则当t2或t3被唤醒后输出的是跳过t0线程生产产品的结果如下:
 * Thread-1...生产...烤鸭45228
 * Thread-0...生产...烤鸭45229
 * Thread-2消费.........烤鸭45229
 * Thread-3消费.........烤鸭45229
 * */
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值