zoukankan      html  css  js  c++  java
  • Java多线程之线程协作

    常见的线程协作方式是:生产者/消费者。

    一个线程作为生产者,生产要处理数据,比如拿一个线程来生产Order,用户每下一单,此线程就生产一个Order对象。

    设置一个仓库,来存放生产出来的Order对象。

    一个线程作为消费者,消费|处理仓库中的Order对象(打印订单、拣货、发货)。


    demo   订单处理流程

    1、用一个类来封装要处理的数据

    public class Order {
        private int id;
        //...
    
        public Order(int id) {
            this.id = id;
        }
    
        public int getId() {
            return id;
        }
    
        //......
    }

    2、仓库

    import java.util.concurrent.BlockingQueue;
    import java.util.concurrent.LinkedBlockingQueue;
    
    public class OrderStorage {
        //使用阻塞队列作为仓库
        private BlockingQueue<Order> queues;
    
        //默认仓库容量为50
        public OrderStorage() {
            this.queues = new LinkedBlockingQueue<>(50);
        }
    
        //初始化仓库容量
        public OrderStorage(int capacity) {
            this.queues = new LinkedBlockingQueue<>(capacity);
        }
    
        //入库
        public void push(Order order) throws InterruptedException {
            queues.put(order);
        }
    
        //出库
        public Order pop() throws InterruptedException {
            return queues.take();  //仓库中没元素时,会阻塞当前线程,直到有元素可弹出。要不怎么叫BlockingQueue
        }
    }

    java.util.concurrent包下有很多并发要使用的类,我们使用的阻塞队列就是这个包下的。concurrent  并发

    队列是先进先出的,先生产的先放到仓库中,先处理。

    3、生产者

    public class ProducerThread extends Thread{
        public static OrderStorage orderStorage = new OrderStorage(100); //仓库容量为100
    
        @Override
        public void run() {
            int i=1;
            while (true){
                Order order = new Order(i);
                try {
                    orderStorage.push(order); //放到仓库中
                    System.out.println("已生产编号为"+i+"的订单");
                    Thread.sleep(1000); //降低速度,方便看效果
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                i++;
            }
        }
    
    }

    容量为100,不是说只能生成50个Order,生产的同时消费者也在消费仓库中的Order。

    4、消费者

    public class ConsumerThread extends Thread {
        private OrderStorage orderStorage=ProducerThread.orderStorage; //消费者和生产者使用的要是同一个仓库
    
        @Override
        public void run() {
            while (true){
                try {
                    Order order = orderStorage.pop(); //如果仓库中没有Order,会阻塞当前线程,直到有Order可以弹出
                    System.out.println("已消费|处理编号为"+order.getId()+"的订单");
                    Thread.sleep(1000); //降低速度,方便看效果
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    
    }

    5、测试类

    public class Test {
        public static void main(String[] args) {
            ProducerThread producerThread = new ProducerThread();
            producerThread.start();
    
            ConsumerThread consumerThread = new ConsumerThread();
            consumerThread.start();
    
        }
    }

    6、效果

    有时候一个订单,会先打印“消费”,再打印“生产”。

    一个Order处理顺序一定是:生产 、入库  ->   出库、消费,要先放到仓库中才能从仓库中获取到。

    只是说生产者、消费者2个线程执行sout时获取到时间片的先后不同。

  • 相关阅读:
    贪心:SPOJ Backup Files
    杂题 SPOJ MOBILE2
    杂题 UVAoj 10000 Longest Paths
    杂题 UVAoj 107 The Cat in the Hat
    DP(斜率优化):HDU 3507 Print Article
    搜索(DLX): POJ 3074 3076 Sudoku
    DLX模板
    PHP代码优化技巧大盘点
    盘点PHP编程常见失误
    PHP Socket 编程详解
  • 原文地址:https://www.cnblogs.com/chy18883701161/p/12545719.html
Copyright © 2011-2022 走看看