• 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();
        }
    }
  • 相关阅读:
    python中的字典
    python中的元组操作
    python中的列表
    python中的内建函数
    python中格式化字符串
    34 哈夫曼编码
    33 构造哈夫曼树
    32 哈夫曼树
    31 树和森林的遍历
    30 森林和二叉树的转化(二叉树与多棵树之间的关系)
  • 原文地址:https://www.cnblogs.com/XYQ-208910/p/4915691.html
Copyright © 2020-2023  润新知