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序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
236 1
|
3月前
|
JSON 网络协议 安全
【Java基础】(1)进程与线程的关系、Tread类;讲解基本线程安全、网络编程内容;JSON序列化与反序列化
几乎所有的操作系统都支持进程的概念,进程是处于运行过程中的程序,并且具有一定的独立功能,进程是系统进行资源分配和调度的一个独立单位一般而言,进程包含如下三个特征。独立性动态性并发性。
250 1
|
4月前
|
数据采集 存储 弹性计算
高并发Java爬虫的瓶颈分析与动态线程优化方案
高并发Java爬虫的瓶颈分析与动态线程优化方案
Java 数据库 Spring
209 0
|
4月前
|
算法 Java
Java多线程编程:实现线程间数据共享机制
以上就是Java中几种主要处理多线程序列化资源以及协调各自独立运行但需相互配合以完成任务threads 的技术手段与策略。正确应用上述技术将大大增强你程序稳定性与效率同时也降低bug出现率因此深刻理解每项技术背后理论至关重要.
379 16
|
5月前
|
缓存 并行计算 安全
关于Java多线程详解
本文深入讲解Java多线程编程,涵盖基础概念、线程创建与管理、同步机制、并发工具类、线程池、线程安全集合、实战案例及常见问题解决方案,助你掌握高性能并发编程技巧,应对多线程开发中的挑战。
|
5月前
|
数据采集 存储 前端开发
Java爬虫性能优化:多线程抓取JSP动态数据实践
Java爬虫性能优化:多线程抓取JSP动态数据实践
|
3月前
|
Java 调度 数据库
Python threading模块:多线程编程的实战指南
本文深入讲解Python多线程编程,涵盖threading模块的核心用法:线程创建、生命周期、同步机制(锁、信号量、条件变量)、线程通信(队列)、守护线程与线程池应用。结合实战案例,如多线程下载器,帮助开发者提升程序并发性能,适用于I/O密集型任务处理。
396 0
|
3月前
|
Java
如何在Java中进行多线程编程
Java多线程编程常用方式包括:继承Thread类、实现Runnable接口、Callable接口(可返回结果)及使用线程池。推荐线程池以提升性能,避免频繁创建线程。结合同步与通信机制,可有效管理并发任务。
198 6
|
6月前
|
Java API 微服务
为什么虚拟线程将改变Java并发编程?
为什么虚拟线程将改变Java并发编程?
354 83