Java:多线程之生产者与消费者

简介:

要求:用两个线程模拟存票、售票过程。但要求每存入一张票,就售出一张票,售出后,再存入,直到售完为止。

用到的知识点:线程等待、唤醒、可能的线程中断异常

下面的方式一和方式二采用的是唤醒所有等待的线程,即wait()和notify()方法

方式一:继承Thread

复制代码
class Tickets //定义(资源)票类
{
    protected int size;//总票数
    int number=0;      //票号
    Boolean available=false;//表示当前是否有票可售
    public Tickets(int size)
    {
      this.size = size;
    }
    public synchronized void store()  //同步方法,实现存票功能
    {
      if(available)  //如果线程还有票可售,则存票线程等待
           try{wait();}
           catch(InterruptedException e){}
           System.out.println(Thread.currentThread().getName()+"存入第【"+(++number)+"】张票");
      available = true;
           notify(); //存票后,唤醒售票线程开始售票
    }

    public synchronized void sale()  //同步方法,实现售票功能
    {
      if(!available)  //如果线程没有票可售,则售票线程等待
           try{wait();}
           catch(InterruptedException e){}
           System.out.println(Thread.currentThread().getName()+"售出第【"+(number)+"】张票");
      available = false;
           notify(); //售票后,唤醒存票线程开始存票
    }
}

class Productor extends Thread  //定义生产者(存票)线程类
{
    private Tickets t;
    public Productor(Tickets t)
    {
      this.t = t;
    }
    public void run()
    {
        while(true)
        {  if(t.number<t.size)
           t.store();
           else
              System.exit(0);
        } 
    }
}

class Costomer extends Thread   //定义消费者(售票)线程类
{
    private Tickets t;
    public Costomer(Tickets t)
    {
      this.t = t;
    }
    public void run()
    { 
      while(true)
        {  if(t.number<=t.size)
           t.sale();
           else
               System.exit(0);
        }
    }
}
class  TicketStoreSale3
{
    public static void main(String[] args) 
    {
        Tickets t = new Tickets(10);

        Productor t1 = new Productor(t);
        Costomer t2 = new Costomer(t);

        t1.start();
        t2.start();
    }
}
复制代码

方式二:实现Runnable接口 

复制代码
class Tickets //定义(资源)票类
{
    protected int size;//总票数
    int number=0;      //票号
    Boolean available=false;//表示当前是否有票可售
    public Tickets(int size)
    {
      this.size = size;
    }
    public synchronized void store()  //同步方法,实现存票功能
    {
      if(available)  //如果线程还有票可售,则存票线程等待
           try{wait();}
           catch(InterruptedException e){}
           System.out.println(Thread.currentThread().getName()+"存入第【"+(++number)+"】张票");
      available = true;
           notify(); //存票后,唤醒售票线程开始售票
    }

    public synchronized void sale()  //同步方法,实现售票功能
    {
      if(!available)  //如果线程没有票可售,则售票线程等待
           try{wait();}
           catch(InterruptedException e){}
           System.out.println(Thread.currentThread().getName()+"售出第【"+(number)+"】张票");
      available = false;
           notify(); //售票后,唤醒存票线程开始存票
    }
}

class Productor implements Runnable  //实现一个接口,生产者(存票)线程类
{
    private Tickets t;
    public Productor(Tickets t)
    {
      this.t = t;
    }
    public void run()
    {
        while(true)
        {  if(t.number<t.size)
           t.store();
           else
              System.exit(0);
        } 
    }
}

class Costomer implements Runnable   //实现一个接口,消费者(售票)线程类
{
    private Tickets t;
    public Costomer(Tickets t)
    {
      this.t = t;
    }
    public void run()
    { 
      while(true)
        {  if(t.number<=t.size)
           t.sale();
           else
               System.exit(0);
        }
    }
}
class  TicketStoreSale
{
    public static void main(String[] args) 
    {
        Tickets t = new Tickets(10);

        Thread t1 = new Thread(new Productor(t));
        Thread t2 = new Thread( new Costomer(t));

        t1.start();
        t2.start();
    }
}
复制代码

 

方式三:在JDK1.5中提供了多线程升级解决方案。
将同步Synchronized替换成显式的Lock操作。
将Object中的wait,notify,notifyAll,替换成了Conditon对象。
该对象可以对Lock锁,进行获取。
该示例中,实现了本方只唤醒对方操作。

复制代码
import java.util.concurrent.locks.*;
class Tickets //定义(资源)票类
{
    protected int size;//总票数
    int number=0;      //票号
    Boolean available=false;//表示当前是否有票可售
    public Tickets(int size)
    {
      this.size = size;
    }
    Lock lock = new ReentrantLock();  //创建锁
    Condition notFull = lock.newCondition(); //创建未满状态
    Condition notEmpty = lock.newCondition();//创建未空状态

    public void store() throws InterruptedException //同步方法,实现存票功能
    {
      lock.lock();
      try
      {
         if(available)  //如果线程还有票可售,则存票线程等待
         notEmpty.await();
         System.out.println(Thread.currentThread().getName()+"存入第【"+(++number)+"】张票");
         available = true;
         notFull.signal();//存票后,唤醒售票线程开始售票
      } 
       finally
        {
          lock.unlock();   //释放锁资源
        }
    }

    public void sale() throws InterruptedException  //同步方法,实现售票功能
    {
      lock.lock();
      try
      {
        if(!available)  //如果线程没有票可售,则售票线程等待
        notFull.await();
        System.out.println(Thread.currentThread().getName()+"售出第【"+(number)+"】张票");
        available = false;
        notEmpty.signal(); //售票后,唤醒存票线程开始存票
      }
      finally
        {
          lock.unlock();  //释放锁资源
        }
    }
}

class Productor implements Runnable  //实现一个接口,生产者(存票)线程类
{
    private Tickets t;
    public Productor(Tickets t)
    {
      this.t = t;
    }
    public void run()
    {
        while(true)
        {  if(t.number<t.size)
            try
            {
                t.store();
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
           
           else
              System.exit(0);
        } 
    }
}

class Costomer implements Runnable   //实现一个接口,消费者(售票)线程类
{
    private Tickets t;
    public Costomer(Tickets t)
    {
      this.t = t;
    }
    public void run()
    { 
      while(true)
        {  if(t.number<=t.size)
          try
          {
             t.sale();
          }
          catch (InterruptedException e)
          {
              e.printStackTrace();
          }
          
           else
               System.exit(0);
        }
    }
}
class  TicketStoreSaleLock
{
    public static void main(String[] args) 
    {
        Tickets t = new Tickets(10);

        Thread t1 = new Thread(new Productor(t));
        Thread t2 = new Thread( new Costomer(t));

        t1.start();
        t2.start();
    }
}
复制代码

 

程序猿神奇的手,每时每刻,这双手都在改变着世界的交互方式!
本文转自当天真遇到现实博客园博客,原文链接:http://www.cnblogs.com/XYQ-208910/p/4915691.html如需转载请自行联系原作者
相关文章
|
3月前
|
JSON 网络协议 安全
【Java】(10)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
234 1
|
3月前
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
248 1
|
4月前
|
数据采集 存储 弹性计算
高并发Java爬虫的瓶颈分析与动态线程优化方案
高并发Java爬虫的瓶颈分析与动态线程优化方案
Java 数据库 Spring
204 0
|
4月前
|
算法 Java
Java多线程编程:实现线程间数据共享机制
以上就是Java中几种主要处理多线程序列化资源以及协调各自独立运行但需相互配合以完成任务threads 的技术手段与策略。正确应用上述技术将大大增强你程序稳定性与效率同时也降低bug出现率因此深刻理解每项技术背后理论至关重要.
376 16
|
5月前
|
缓存 并行计算 安全
关于Java多线程详解
本文深入讲解Java多线程编程,涵盖基础概念、线程创建与管理、同步机制、并发工具类、线程池、线程安全集合、实战案例及常见问题解决方案,助你掌握高性能并发编程技巧,应对多线程开发中的挑战。
|
5月前
|
数据采集 存储 前端开发
Java爬虫性能优化:多线程抓取JSP动态数据实践
Java爬虫性能优化:多线程抓取JSP动态数据实践
|
6月前
|
Java API 调度
从阻塞到畅通:Java虚拟线程开启并发新纪元
从阻塞到畅通:Java虚拟线程开启并发新纪元
391 83
|
6月前
|
安全 算法 Java
Java 多线程:线程安全与同步控制的深度解析
本文介绍了 Java 多线程开发的关键技术,涵盖线程的创建与启动、线程安全问题及其解决方案,包括 synchronized 关键字、原子类和线程间通信机制。通过示例代码讲解了多线程编程中的常见问题与优化方法,帮助开发者提升程序性能与稳定性。
309 0
|
存储 安全 Java
解锁Java并发编程奥秘:深入剖析Synchronized关键字的同步机制与实现原理,让多线程安全如磐石般稳固!
【8月更文挑战第4天】Java并发编程中,Synchronized关键字是确保多线程环境下数据一致性与线程安全的基础机制。它可通过修饰实例方法、静态方法或代码块来控制对共享资源的独占访问。Synchronized基于Java对象头中的监视器锁实现,通过MonitorEnter/MonitorExit指令管理锁的获取与释放。示例展示了如何使用Synchronized修饰方法以实现线程间的同步,避免数据竞争。掌握其原理对编写高效安全的多线程程序极为关键。
305 1

热门文章

最新文章