zoukankan      html  css  js  c++  java
  • 多线程案例:生产者和消费者



    以继承Thread实现:

               

    package example;

    /**
    * 所有synchronized方法持有同一把this锁,
    * synchronized方法执行到wait()时放锁,
    * 让其他线程可以进入相应的synchronized方法
    * @author 姚丽辉
    */
    public class Producter_Consumer {
    private int     size = 5;      //容器大小
    private int     remain = size;      //剩余空间
    private int[] common = new int[size];//容器,该信号量用于同步生产者和消费者

    private synchronized void product(int i) throws InterruptedException {
         if (remain > 0) {
          notify();//通知生产者继续
         }
         common[i % size] = i;
         remain--;
         System.out.println("product:" + i);
         if (remain == 0) {
          System.out.println("product wait");
          wait();//让生产者等待
         }
    }

    private synchronized void consume(int i) throws InterruptedException {
         if ((size - remain) > 0) {
          notify();//通知消费者继续
         }
         System.out.println("consume:" + common[i % size]);
         remain++;
         if (remain == size) {
          System.out.println("consume wait");
          wait();//让消费者等待
         }
    }

    class Producter extends Thread {
         public void run() {
          for (int i = 1; true; i++) {
           try {
            product(i);
            sleep((int) (Math.random() * 5000));
           } catch (InterruptedException e) {
            e.printStackTrace();
           }
          }
         }
    }

    class Consumer extends Thread {
         public void run() {
          for (int i = 1; true; i++) {
           try {
            consume(i);
            sleep((int) (Math.random() * 5000));
           } catch (InterruptedException e) {
            e.printStackTrace();
           }
          }
         }
    }

    private void start() {
         Producter p = new Producter();
         Consumer c = new Consumer();
         p.start();
         c.start();
    }

    public static void main(String[] args) {
         Producter_Consumer m = new Producter_Consumer();
         m.start();
    }

    }











    实现Runnable接口


    1。生产和消费的产品抽象类

    //预留

    public abstract class Product {
        
        public String name;
        public abstract String toString();

    }


    2。一个具体的产品类

    public class AProduct extends Product {

        public AProduct(String pname) {
            super();
            name = pname;
            // TODO Auto-generated constructor stub
        }

        public String toString() {
            // TODO Auto-generated method stub
            return name;
        }

    }


    3。容器类(仓库)

    import java.util.ArrayList;

    /*
     * 存放生产者和消费者的产品队列
     * */

    public class Container {

        private ArrayList arrList = new ArrayList();

        private int LENGTH = 10;

        public boolean isFull() {
            return arrList.size() == LENGTH;
        }

        public boolean isEmpty() {
            return arrList.isEmpty();
        }

        /* 如果此处不加synchronized锁,那么也可以再调用push的地方加锁
        * 既然此处加了锁,那么再别的地方可以不加锁
        */

        public synchronized void push(Object o) {
            arrList.add(o);
        }

        // 如果此处不加synchronized锁,那么也可以再调用push的地方加锁

        public synchronized Object pop() {
            Object lastOne = arrList.get(arrList.size() - 1);
            arrList.remove(arrList.size() - 1);

            return lastOne;
        }
    }


    4。休息一会,生产者和消费者都要休息,因此作为抽象基类


    public abstract class Sleep {

        public void haveASleep() throws InterruptedException {

            Thread.sleep((long) (Math.random() * 3000));
        }

    }

    // sleep让出cpu时间给其他线程执行.也许你会问,既然我已经wait了,为什么还要sleep?

     // wait()的作用就是阻塞当前线程并且释放对象的
    给别人(一般是等待队列中的第一个线程)

     // Thead.sleep()也是阻塞当前线程,但不释放锁。

     // sleep()方法是使线程停止一段时间的方法。

     // 在sleep 时间间隔期满后,线程不一定立即恢复执行。

     // 这是因为在那个时刻,其它线程可能正在运行而且没有被调度为放弃执行,除非 (a)“醒来”的线程具有更高的优先级。

     // (b)正在运行的线程因为其它原因而阻塞。 wait()是线程交互时,如果线程对一个同步对象x

     // 发出一个wait()调用,该线程会暂停执行,被调对象进入等待状态,直到被唤醒或等待时间到。

     // 当调用wait()后,线程会释放掉它所占有的“锁标志”,从而使线程所在对象中的其它synchronized数据可被别的线程使用。

     // waite()和notify()因为会对对象的“锁标志”进行操作,所以它们必须在synchronized函数或synchronized

     

    /*
     * 消费者线程
     * */

    public class Consumer extends Sleep implements Runnable {
        private Container contain = null;

        public Consumer(Container contain) {
            super();
            this.contain = contain;
        }

        public void run() {
            // TODO Auto-generated method stub

            while (true) {
                synchronized (contain) {
                    while (contain.isEmpty()) {
                        try {
                            contain.wait();
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block

                            e.printStackTrace();
                        }
                    }
                }
                consume();//消费

                try {
                    haveASleep();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block

                    e.printStackTrace();
                }
                synchronized (contain) {
                    contain.notify();
                }
            }
        }

        private void consume() {
            Product a = (AProduct) contain.pop();
            System.out.println("消费了一个产品" + a.toString());
        }
    }

    /*
     * 生产者线程
     * */

    public class Producator extends Sleep implements Runnable {
        private Container contain = null;

        public Producator(Container contain) {
            super();
            this.contain = contain;
        }

        public void run() {
            // TODO Auto-generated method stub

            while (true) {
                synchronized (contain) {
                    while (contain.isFull()) {
                        try {
                            contain.wait();// 阻塞当前线程,当前线程进入等待队列。这个时候只有等待别的线程来唤醒自己了。

                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block

                            e.printStackTrace();
                        }
                    }
                }
                producer();// 生产一个产品

                try {
                    haveASleep();
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block

                    e.printStackTrace();
                }
                synchronized (contain) {
                    contain.notify();// 唤醒等待队列中正在等待的第一个线程,让其执行。

                }
            }
        }

        public void producer() {
            Product aProduct = new AProduct("pp:" + String.valueOf(Math.random()));
            System.out.println("生产了一个产品:" + aProduct.toString());
            contain.push(aProduct);
        }

    }

    5 写一个测试吧:

    public class TestMain {

        /**
         * @param args
         */

        public static void main(String[] args) {
            // TODO Auto-generated method stub

            Container contain = new Container();
            Producator p = new Producator(contain);
            Consumer c = new Consumer(contain);
            Thread pt = new Thread(p);
            Thread ct = new Thread(c);
            pt.start();
            ct.start();
        }

    }

     

     

    1.生产和消费的产品抽象类:
    public abstract class Product {
        public String name;
        public abstract String toString();
    }

    2.一个具体的产品类:

    public class AProduct extends Product {
        public AProduct(String name) {
            this.name = name;
            // TODO Auto-generated constructor stub
        }
        public String toString() {
            // TODO Auto-generated method stub
            return this.name;
        }
    }

    3.容器类(仓库):

    import java.util.ArrayList;

    /*
     * 存放生产者和消费者的产品队列
     * */

    public class Container {
        private ArrayList arrList = new ArrayList();
        private int LENGTH = 10;
        public boolean isFull() {
            return arrList.size()==LENGTH;
        }
        public boolean isEmpty() {
            return arrList.isEmpty();
        }

        /* 如果此处不加synchronized锁,那么也可以再调用push的地方加锁
        * 既然此处加了锁,那么再别的地方可以不加锁
        */

        public synchronized void push(Object o) {
            arrList.add(o);
        }
        // 如果此处不加synchronized锁,那么也可以再调用push的地方加锁
        public synchronized Object pop() {
            Object lastOne = arrList.get(arrList.size()- 1);
            arrList.remove(arrList.size()- 1);
            return lastOne;
        }
    }

    4.休息一会,生产者和消费者都要休息,因此作为抽象基类:

    public abstract class Sleep {
        public void haveASleep() throws InterruptedException {
            Thread.sleep((long)(Math.random()* 3000));
        }
    }

    /*
     * 消费者线程
     * */

    public class Consumer extends Sleep implements Runnable {
        private Container contain =null;
        public Consumer(Container contain) {
            this.contain = contain;
        }
        public void run() {
            // TODO Auto-generated method stub
            while(true) {
                synchronized(contain) {
                    while(contain.isEmpty()) {
                        try{
                            contain.wait();
                        }catch(InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                }
                consume();//消费
                try {
                    haveASleep();
                }catch(InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                synchronized(contain) {
                    contain.notify();
                }
            }
        }
        private void consume() {
            Product a = (AProduct)contain.pop();
            System.out.println("消费了一个产品"+ a.toString());
        }
    }

    /*
     * 生产者线程
     * */

    public class Producator extends Sleep implements Runnable {
        private Container contain = null;
        public Producator(Container contain) {
            super();
            this.contain = contain;
        }
        public void run() {
            // TODO Auto-generated method stub
            while(true) {
                synchronized(contain) {
                    while(contain.isFull()) {
                        try{
                            contain.wait();// 阻塞当前线程,当前线程进入等待队列。这个时候只有等待别的线程来唤醒自己了。
                        }catch(InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                    }
                }
                producer();// 生产一个产品
                try {
                    haveASleep();
                }catch(InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                synchronized(contain) {
                    contain.notify();// 唤醒等待队列中正在等待的第一个线程,让其执行。
                }
            }
        }
        public void producer() {
            Product aProduct = new AProduct("pp:"+String.valueOf((int)(10*Math.random())));
            System.out.println("生产了一个产品:"+ aProduct.toString());
            contain.push(aProduct);
        }
    }

    5. 写一个测试:

    public class TestMain {
        /**
         * @param args
         */

        public static void main(String[] args) {
            // TODO Auto-generated method stub
            Container contain = new Container();
            Producator p = new Producator(contain);
            Consumer c = new Consumer(contain);
            Thread pt =new Thread(p);
            Thread ct =new Thread(c);
            pt.start();
            ct.start();
        }
    }

     

     

    好了,看看执行结果吧:

    生产了一个产品:pp:0.5010546528255287
    生产了一个产品:pp:0.08173509855014827
    消费了一个产品pp:0.5010546528255287
    生产了一个产品:pp:0.7022996270428004
    生产了一个产品:pp:0.6245814751574797
    生产了一个产品:pp:0.2839979336434959
    生产了一个产品:pp:0.49694821923381394
    消费了一个产品pp:0.49694821923381394
    生产了一个产品:pp:0.7830305503500449
    消费了一个产品pp:0.7830305503500449
    消费了一个产品pp:0.2839979336434959
    生产了一个产品:pp:0.8563793401031702
    消费了一个产品pp:0.8563793401031702
    生产了一个产品:pp:0.32584165485489935
    生产了一个产品:pp:0.28527005336129474
    消费了一个产品pp:0.28527005336129474
    生产了一个产品:pp:0.9941746668279293
    消费了一个产品pp:0.9941746668279293
    消费了一个产品pp:0.32584165485489935
    生产了一个产品:pp:0.7338057107242784
    生产了一个产品:pp:0.7582181553056575
    消费了一个产品pp:0.7582181553056575
    生产了一个产品:pp:0.7563821078081756
    生产了一个产品:pp:0.5659487332730776
    消费了一个产品pp:0.5659487332730776
    生产了一个产品:pp:0.8737523015090108
    消费了一个产品pp:0.8737523015090108
    消费了一个产品pp:0.7563821078081756
    消费了一个产品pp:0.7338057107242784
    生产了一个产品:pp:0.37558043387512685
    消费了一个产品pp:0.37558043387512685
    生产了一个产品:pp:0.5152849555101155
    消费了一个产品pp:0.5152849555101155
    消费了一个产品pp:0.6245814751574797
    生产了一个产品:pp:0.2839737014600726
    生产了一个产品:pp:0.14867665839711486
    消费了一个产品pp:0.14867665839711486
    消费了一个产品pp:0.2839737014600726
    生产了一个产品:pp:0.7526721181825591
    消费了一个产品pp:0.7526721181825591
    生产了一个产品:pp:0.7413376261101124
    生产了一个产品:pp:0.6122237252752002
    消费了一个产品pp:0.6122237252752002
    生产了一个产品:pp:0.5506019686616669
    消费了一个产品pp:0.5506019686616669
    消费了一个产品pp:0.7413376261101124
    消费了一个产品pp:0.7022996270428004
    消费了一个产品pp:0.08173509855014827
    生产了一个产品:pp:0.4210845970052677
    生产了一个产品:pp:0.38826328968056667
    消费了一个产品pp:0.38826328968056667
    生产了一个产品:pp:0.8431303537483879
    消费了一个产品pp:0.8431303537483879
    消费了一个产品pp:0.4210845970052677
    生产了一个产品:pp:0.34155093374925427
    消费了一个产品pp:0.34155093374925427
    生产了一个产品:pp:0.6344976720730141
    消费了一个产品pp:0.6344976720730141
    生产了一个产品:pp:0.8363082839823789
    生产了一个产品:pp:0.2811236642618875
    消费了一个产品pp:0.2811236642618875
    生产了一个产品:pp:0.5203709922238451
    消费了一个产品pp:0.5203709922238451
    生产了一个产品:pp:0.33594716801656854
    消费了一个产品pp:0.33594716801656854
    生产了一个产品:pp:0.6769814698429393
    消费了一个产品pp:0.6769814698429393
    生产了一个产品:pp:0.9745584834485369
    消费了一个产品pp:0.9745584834485369
    生产了一个产品:pp:0.8499765864829567
    消费了一个产品pp:0.8499765864829567
    生产了一个产品:pp:0.6281666437831501
    生产了一个产品:pp:0.7009942032367253
    生产了一个产品:pp:0.6354980777267613
    消费了一个产品pp:0.6354980777267613
    生产了一个产品:pp:0.5343260452244308
    生产了一个产品:pp:0.7760536310129287
    消费了一个产品pp:0.7760536310129287
    生产了一个产品:pp:0.1571400849830824
    消费了一个产品pp:0.1571400849830824
    生产了一个产品:pp:0.7219309859537877
    消费了一个产品pp:0.7219309859537877
    消费了一个产品pp:0.5343260452244308
    生产了一个产品:pp:0.27212965262811006
    生产了一个产品:pp:0.6767042422791443
    消费了一个产品pp:0.6767042422791443
    生产了一个产品:pp:0.5569267542654116
    消费了一个产品pp:0.5569267542654116
    生产了一个产品:pp:0.2711661616389571
    消费了一个产品pp:0.2711661616389571
    消费了一个产品pp:0.27212965262811006
    消费了一个产品pp:0.7009942032367253
    消费了一个产品pp:0.6281666437831501
    生产了一个产品:pp:0.2002128062138283
    生产了一个产品:pp:0.1922231902417787
    消费了一个产品pp:0.1922231902417787
    消费了一个产品pp:0.2002128062138283
    生产了一个产品:pp:0.17966888984989626
    生产了一个产品:pp:0.3671850675304076
    消费了一个产品pp:0.3671850675304076
    生产了一个产品:pp:0.939554979545969
    消费了一个产品pp:0.939554979545969
    生产了一个产品:pp:0.40458123731585616
    生产了一个产品:pp:0.5295806686705823
    消费了一个产品pp:0.5295806686705823
    生产了一个产品:pp:0.20237224414120825
    生产了一个产品:pp:0.3318491844902224
    生产了一个产品:pp:0.6154098900759897
    消费了一个产品pp:0.6154098900759897

    ……

  • 相关阅读:
    Redis源码解析:28集群(四)手动故障转移、从节点迁移
    Redis源码解析:27集群(三)主从复制、故障转移
    Redis源码解析:26集群(二)键的分配与迁移
    centos 6.5 安装composer
    Centos安装php高版本
    CentOS快速搭建LAMP环境
    封装类似thinkphp连贯操作数据库的Db类(简单版)。
    php封装pdo操作数据的工具类
    php中使用mysqli和pdo扩展,测试mysql数据库的执行效率。
    php中使用mysqli和pdo扩展,测试连接mysql数据库的效率。
  • 原文地址:https://www.cnblogs.com/smallfa/p/1116864.html
Copyright © 2011-2022 走看看