Java多线程之线程协作

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

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

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

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


demo   订单处理流程

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

1public class Order { 2 private int id; 3 //... 4 5 public Order(int id) { 6 this.id = id; 7 } 8 9 public int getId() { 10 return id; 11 } 12 13 //...... 14}

2、仓库

1import java.util.concurrent.BlockingQueue; 2import java.util.concurrent.LinkedBlockingQueue; 3 4public class OrderStorage { 5 //使用阻塞队列作为仓库 6 private BlockingQueue<Order> queues; 7 8 //默认仓库容量为50 9 public OrderStorage() { 10 this.queues = new LinkedBlockingQueue<>(50); 11 } 12 13 //初始化仓库容量 14 public OrderStorage(int capacity) { 15 this.queues = new LinkedBlockingQueue<>(capacity); 16 } 17 18 //入库 19 public void push(Order order) throws InterruptedException { 20 queues.put(order); 21 } 22 23 //出库 24 public Order pop() throws InterruptedException { 25 return queues.take(); //仓库中没元素时,会阻塞当前线程,直到有元素可弹出。要不怎么叫BlockingQueue 26 } 27}

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

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

3、生产者

1public class ProducerThread extends Thread{ 2 public static OrderStorage orderStorage = new OrderStorage(100); //仓库容量为100 3 4 @Override 5 public void run() { 6 int i=1; 7 while (true){ 8 Order order = new Order(i); 9 try { 10 orderStorage.push(order); //放到仓库中 11 System.out.println("已生产编号为"+i+"的订单"); 12 Thread.sleep(1000); //降低速度,方便看效果 13 } catch (InterruptedException e) { 14 e.printStackTrace(); 15 } 16 i++; 17 } 18 } 19 20}

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

4、消费者

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

5、测试类

1public class Test { 2 public static void main(String[] args) { 3 ProducerThread producerThread = new ProducerThread(); 4 producerThread.start(); 5 6 ConsumerThread consumerThread = new ConsumerThread(); 7 consumerThread.start(); 8 9 } 10}

6、效果

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

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

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

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

手写Java HashMap源码

HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22

一 java线程的等待/通知模型

java中线程之间的通信问题,有这么一个模型:一个线程修改了一个对象的值,而另一个线程感知到了变化,然后进行相应的操作,整个过程开始于一个线程,而最终执行又是另一个线程。前者是生产者,后者就是消费者,也可以叫做生产者消费者问题生产者生产了产品,如何通知消费者?下面就介绍下java线程中的等待通知机制。其它语言类似,自行研究。代码附上下面是以买小

4、jstack查看线程栈信息

1、介绍利用jps、top、jstack命令找到进程中耗时最大的线程,以及线程状态等等,同时最后还可以显示出死锁的线程查找:FoundoneJavaleveldeadlock即可1、jps获得进程号!(https://oscimg.oschina.net/oscnet/da00a309fa6

03.Android崩溃Crash库之ExceptionHandler分析

目录总结00.异常处理几个常用api01.UncaughtExceptionHandler02.Java线程处理异常分析03.Android中线程处理异常分析04.为何使用setDefaultUncaughtExceptionHandler前沿上一篇整体介绍了crash崩溃