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();
    }
}
原文地址:https://www.cnblogs.com/XYQ-208910/p/4915691.html