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();
    }
}
时间: 2024-10-10 17:48:33

Java:多线程之生产者与消费者的相关文章

java多线程实现生产者与消费者---经典问题

前几天老师领着学习了一下单线程和多线程的题目. 这里是操作系统中非常经典的题目,生产者和消费者的题,这里涉及的是仓库, 只有一个人(生产者或消费者)进入,另一个人只有等待. 这里的重点是关于传值的问题.一定要保持一致,不然,对于存和取 的对象,就可能出现多个. //========================================================================// 仓库类 //====================================

Java多线程的生产者与消费者模型,线程间的通信

java多线程中的生产者与消费者模式:首先有一个阻塞队列,生产者将生产的东西放到队列里,消费者再从队列中取.当队列中的东西数量达到其容量就发生阻塞. import java.util.Random; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; import jav

JAVA多线程之生产者消费者

生产者消费者并发编程: 假设仓库有10个仓位,分别有10个生产者和10个消费者,生产者不断生产产品,放入仓库的仓位中,而消费者则不断从仓库中获取产品, 如果仓库已满,则生产者要等待,等消费者消费后,空出仓位后,再继续放入产品. 反之如果仓库已空,则消费者要等待,等待生产者生产出产品后,再继续消费产品. 关于生产者.消费者有四种实现方式 1,wait,nofity方式 2,ReentrantLock锁的await()和signal() 3,阻塞队列的方式 4,Semaphore 信号量方式 下面分

java多线程解决生产者消费者问题

import java.util.ArrayList; import java.util.List; /** * Created by ccc on 16-4-27. */ public class Test { public static void main(String[] args) { GunClip clip = new GunClip(); Producer p = new Producer(clip); customer c = new customer(clip); p.star

java多线程模拟生产者消费者问题,公司面试常常问的题。。。

package com.cn.test3; //java多线程模拟生产者消费者问题 //ProducerConsumer是主类,Producer生产者,Consumer消费者,Product产品 //Storage仓库 //批注:我把输出结果写在程序以下了,你能够看一下,事实上非常easy的,你想象一下产品从生产,到取出的一个生产线,我们定义两个线程,生产者线程,和消费者线程,一个是生产者不停的生产产品并放入数量有限的指定槽内,而消费者从指定槽依次取出产品,现实中的流水车间也相似于此. publ

java_多线程_生产者与消费者(并发协作)

对于多线程程序来说,不管任何编程语言,生产者和消费者模型都是最经典的.就像学习每一门编程语言一样,Hello World!都是最经典的例子. 实际上,准确说应该是“生产者-消费者-仓储”模型,离开了仓储,生产者消费者模型就显得没有说服力了.对于此模型,应该明确一下几点:1.生产者仅仅在仓储未满时候生产,仓满则停止生产.2.消费者仅仅在仓储有产品时候才能消费,仓空则等待.3.当消费者发现仓储没产品可消费时候会通知生产者生产.4.生产者在生产出可消费产品时候,应该通知等待的消费者去消费. packa

Java 多线程 简单实例 (消费者与生成者)的关系

PS::线程这套东西在PHP里完全是不存在的概念,有待进一步的学习: PS::这个实例是根据书本上的知识进行扩展的,理解程度50%左右吧! 1.定义生产消费环境 package second; public class Queue { int value = 0; boolean isEmpty = true; /** * 生产者 * @param v */ public synchronized void put(int v){ if(!isEmpty){//如果存在数据没有被消费 try{

Java中的生产者、消费者问题

Java中的生产者.消费者问题描述: 生产者-消费者(producer-consumer)问题, 也称作有界缓冲区(bounded-buffer)问题, 两个进程共享一个公共的固定大小的缓冲区(仓库). 其中一个是生产者, 用于将产品放入仓库: 另外一个是消费者, 用于从仓库中取出产品消费. 问题出现在当仓库已经满了, 而此时生产者还想向其中放入一个新的产品的情形, 其解决方法是让生产者此时进行等待, 等待消费者从仓库中取走了一个或者多个产品后再去唤醒它. 同样地, 当仓库已经空了, 而消费者还

java多线程之生存者与消费者(Java编程思想)

1.Restaurant package Produce; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; class Meal { private final int orderNum; public Meal(int orderNum) { this.orderNum = orderNum; } @

Java多线程:生产者消费者更佳的解决方法(确定不会出现死锁)

今天看了一片博文,讲Java多线程之线程的协作,其中作者用程序实例说明了生产者和消费者问题,但我及其他读者发现程序多跑几次还是会出现死锁,百度搜了下大都数的例子也都存在bug,经过仔细研究发现其中的问题,并解决了,感觉有意义贴出来分享下. 下面首先贴出的是有bug的代码,一个4个类,Plate.java: package CreatorAndConsumer; import java.util.ArrayList; import java.util.List; /** * 盘子,表示共享的资源