Java基础教程:多线程基础(3)——阻塞队列

Java基础教程:多线程基础(3)——阻塞队列

快速开始

引入问题

  生产者消费者问题是线程模型中的经典问题:生产者和消费者在同一时间段内共用同一存储空间,生产者向空间里生产数据,而消费者取走数据

模拟情景

  这里我们实现如下的情况的生产-消费模型:

生产者不断交替地生产两组数据“姓名--1-->内容--1”,“姓名--2-->内容--2”,这里的“姓名--1”和“姓名--2”模拟为数据的名称,“内容--1 ”和“内容--2 ”模拟为数据的内容

由于本程序中牵扯到线程运行的不确定性,因此可能会出现以下问题:

  1.假设生产者线程刚向数据存储空间添加了数据的名称,还没有加入该信息的内容,程序就切换到了消费者线程,消费者线程把信息的名称和上一个信息的内容联系到了一起;

  2.生产者生产了若干条数据,消费者才可以取数据,或者是,消费者取完一次数据后,还没等生产者放入新的数据,又重复取出了已取过的数据。

通过分析我们可知:

  第一个问题可以通过同步来解决,第二个问题就需要用到线程通信。生产者线程放入数据后,通知消费者线程取出数据,消费者线程取出数据后,通知生产者线程生产数据,这里用wait\notigy机制来实现。

Java代码

定义信息类

package thread;public class Info {private String name = "name";private String content = "content";//设置标志位,用来进行线程通信private boolean flag =true;/*** 设置消息,此处用到线程同步* @param name* @param content*/public synchronized void set(String name,String content){while (!flag){try {super.wait();} catch (InterruptedException e) {e.printStackTrace();}}this.name=name; //设置名称try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}this.content=content; //设置内容flag =false; //设置标志位,表示现在生产停止,可以取走!}public synchronized void get(){while (flag){try {super.wait();} catch (InterruptedException e) {e.printStackTrace();}}try {Thread.sleep(300);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(name +" --> " + content) ;flag  = true ;  // 改变标志位,表示可以生产super.notify();}}  

定义生产者

public class Producer implements Runnable {private Info info=null;public Producer(Info info){this.info=info;}@Overridepublic void run() {boolean flag = true ;   // 定义标记位for(int i=0;i<10;i++){if(flag){this.info.set("姓名--1","内容--1") ;    // 设置名称flag = false ;}else{this.info.set("姓名--2","内容--2") ;    // 设置名称flag = true ;}}}
}

定义消费者

public class Consumer implements Runnable {private Info info = null ;public Consumer(Info info){this.info = info ;}public void run(){for(int i=0;i<10;i++){this.info.get() ;}}public static void main(String[] args) {Info info = new Info(); // 实例化Info对象Producer pro = new Producer(info) ; // 生产者Consumer con = new Consumer(info) ; // 消费者new Thread(pro).start() ;//启动了生产者线程后,再启动消费者线程try{Thread.sleep(500) ;}catch(InterruptedException e){e.printStackTrace() ;}new Thread(con).start() ;}
}

 使用阻塞队列来实现相同功能

引入BlockingQueue

  任何有效的生产者-消费者问题解决方案都是通过控制生产者put()方法(生产资源)和消费者take()方法(消费资源)的调用来实现的,一旦你实现了对方法的阻塞控制,那么你将解决该问题。Java通过BlockingQueue提供了开箱即用的支持来控制这些方法的调用(一个线程创建资源,另一个消费资源)。java.util.concurrent包下的BlockingQueue接口是一个线程安全的可用于存取对象的队列

  

  BlockingQueue是一种数据结构支持一个线程往里存资源,另一个线程从里取资源。这正是解决生产者消费者问题所需要的,那么让我们开始解决该问题吧。

Java代码

消息类

public class InfoPlus {private String name = "name";private String content = "content";public InfoPlus(String name, String content) {this.name = name;this.content = content;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getContent() {return content;}public void setContent(String content) {this.content = content;}@Overridepublic String toString() {return "InfoPlus{" +"name='" + name + '\'' +", content='" + content + '\'' +'}';}
}

生产者

import java.util.concurrent.BlockingQueue;public class ProducerPlus implements Runnable {private BlockingQueue<InfoPlus> queue;public ProducerPlus(BlockingQueue<InfoPlus> queue) {this.queue = queue;}@Overridepublic void run() {for (int i=0;i<10;i++){try {Thread.sleep(1000);queue.put(new InfoPlus("name"+i,"content"+i));} catch (InterruptedException e) {e.printStackTrace();}}}
}

消费者

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;public class ConsumerPlus implements Runnable{private BlockingQueue<InfoPlus> queue;public ConsumerPlus(BlockingQueue<InfoPlus> queue) {this.queue = queue;}public void run() {while (true) {try {System.out.println(this.queue.take());} catch (InterruptedException e) {e.printStackTrace();}}}public static void main(String[] args) {BlockingQueue<InfoPlus> blockingQueue = new LinkedBlockingDeque<>();ProducerPlus producerPlus = new ProducerPlus(blockingQueue);ConsumerPlus consumerPlus = new ConsumerPlus(blockingQueue);ConsumerPlus consumerPlus1 = new ConsumerPlus(blockingQueue);new Thread(producerPlus).start();new Thread(consumerPlus).start();new Thread(consumerPlus1).start();}
}

 

转载于:https://www.cnblogs.com/MrSaver/p/9409838.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/249800.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

001.Linux开机启动过程

相关Linux启动过程解析&#xff0c;此作为通用启动参考&#xff1a; 转载于:https://www.cnblogs.com/itzgr/p/10285833.html

【01】《正则表达式必知必会》(已看)(仅存放)

【01】《正则表达式必知必会》 共149页。扫描版&#xff0c;中文版。Sams Teach Yourselef Regular Expressions in 10 minutesBen Forta著。杨涛 翻译【】魔芋&#xff1a;这本书已经没有用了。内容已吸收。内容较为基础&#xff0c;也很全面。** 附件列表 链接&#xff1a;ht…

什么是高并发,如何避免高并发

之前我将高并发的解决方法误认为是线程或者是队列可以解决&#xff0c;因为高并发的时候是有很多用户在访问&#xff0c;导致出现系统数据不正确、丢失数据现象&#xff0c;所以想到 的是用队列解决&#xff0c;其实队列解决的方式也可以处理&#xff0c;比如我们在竞拍商品、转…

到底多大才算高并发?

一、什么是高并发 定义&#xff1a; 高并发(High Concurrency)是使用技术手段使系统可以并行处理很多请求。关键指标&#xff1a; -响应时间(Response Time) -吞吐量(Throughput) -每秒查询率QPS(Query Per Second) -每秒事务处理量TPS(Transaction Per Second) -同时在…

eclipse安装maven插件

1、在线安装插件 a.打开eclipse&#xff0c;菜单“Help”-“Install New Software...” b.在Work with 地址栏输入&#xff1a;http://download.eclipse.org/releases/对应eclipse版本名称 c.在filter框中输入maven d.选择“Collaboration”-“m2e - Maven Integration for Ecl…

VS2017 网站打包发布生成的文件中包含.pdb文件,解决办法

右键点击项目属性&#xff0c;选择打包/发布 Web&#xff0c;勾选 排除生成的调试符号&#xff1a; 再次发布&#xff0c;就不会再生成.pdb文件 转载于:https://www.cnblogs.com/JoinLet/p/10297254.html

分布式学习路线

由于分布式系统所涉及到的领域众多&#xff0c;知识庞杂&#xff0c;很多新人在最初往往找不到头绪&#xff0c;不知道从何处下手来一步步学习分布式架构。 本文试图通过一个最简单的、常用的分布式系统&#xff0c;来阐述分布式系统中的一些基本问题。 负载均衡分布式缓存分…

IDEA开发vue.js卡死问题

在执行cnpm install后会在node_modules这个文件下面生成vue的相关依赖文件&#xff0c; 这个时候当执行cnpm run dev命令时&#xff0c;会导致IDEA出现卡死的问题&#xff0c;解决方法如下&#xff1a; 转载于:https://www.cnblogs.com/heqiuyong/p/10301925.html

各种缓存介绍

说起缓存相关技术&#xff0c;老多了&#xff0c; memcache、redis、squid、varnish、web cache、 CDN等等。缓存技术五花八门&#xff0c;但这些技术间有什么共性的地方&#xff0c;又有什么不同的地方呢&#xff1f;答案肯定是有的&#xff0c;这次为大家分享及整理一下缓存方…

CentOS6.8 安装node.js npm

环境&#xff1a;CentOS6.8_X64系统 一、到官方下载最新的编译好的安装文件&#xff0c;目前是6.9.4。 $>cd /usr/local/src #定位到这个目录&#xff0c;下载的文件会在这个目录#使用wget下载&#xff08;这个内置命令&#xff09; $>wget https://nodejs.org/dist/v8.1…

[上下界网络流][二分] Bzoj P2406 矩阵

题目描述 输入输出格式 输入格式&#xff1a; 第一行两个数n、m&#xff0c;表示矩阵的大小。 接下来n行&#xff0c;每行m列&#xff0c;描述矩阵A。 最后一行两个数L&#xff0c;R。 输出格式&#xff1a; 第一行&#xff0c;输出最小的答案&#xff1b; 输入输出样例 输入样…

PYTHON 爬虫笔记七:Selenium库基础用法

知识点一&#xff1a;Selenium库详解及其基本使用 什么是Selenium selenium 是一套完整的web应用程序测试系统&#xff0c;包含了测试的录制&#xff08;selenium IDE&#xff09;,编写及运行&#xff08;Selenium Remote Control&#xff09;和测试的并行处理&#xff08;Sele…

RPC简介及框架选择

简单介绍RPC协议及常见框架&#xff0c;对比传统restful api和RPC方式的优缺点。常见RPC框架&#xff0c;gRPC及序列化方式Protobuf等 HTTP协议 http协议是基于tcp协议的&#xff0c;tcp协议是流式协议&#xff0c;包头部分可以通过多出的\r\n来分界&#xff0c;包体部分如何分…

JAVA中几种常用的RPC框架介绍

RPC是远程过程调用的简称&#xff0c;广泛应用在大规模分布式应用中&#xff0c;作用是有助于系统的垂直拆分&#xff0c;使系统更易拓展。Java中的RPC框架比较多&#xff0c;各有特色&#xff0c;广泛使用的有RMI、Hessian、Dubbo等。RPC还有一个特点就是能够跨语言&#xff0…

WC2019 自闭记

不咕了 Day 1 2019/1/24 辣么快就到冬令营了&#xff0c;还沉迷于被柿子吊打的状态的菜鸡一时半会还反应不过来。我们学校这次分头去的冬令营&#xff0c;差点上不了车。这次做的动车居然直达广州&#xff0c;强啊。 然鹅还是到太晚&#xff0c;没饭吃了。路上花了15大洋买了个…

跨语言RPC框架Thrift详解

一、 概念 Apache的Thrift软件框架&#xff0c;是用来进行可伸缩的、跨语言的服务开发&#xff0c;它通过一个代码生成引擎来构建高效、无缝的服务&#xff0c;这些服务能够实现跨语言调度&#xff0c;目前支持的语言有&#xff1a; C, Java, Python, PHP, Ruby, Erlang, Perl,…

小知识

1.时间格式的处理 new Date().format(yyyy-MM-dd hh:mm:ss) 2.保留两位小数的方法 element.recTime element.recTime.toFixed(2) 3.如何判断一个对象为空的方法 JSON.stringify(this.getEcho) ! "{}" 4.判断时间是否为标准格式的方法 (this.formValidate.outDateti…

MTK-TP(电阻屏校准程序ts_lib移植)

现今的项目中已经很少有使用电阻TP&#xff0c;但总有些奇怪的需求。如果项目中遇到需要校准电阻屏如何保证较快且较稳的调试TP呢。这里介绍使用ts_lib库来进行调试。 当然也可以使用一些常见的校准算法&#xff0c;采集5点&#xff0c;但最终的公式应该是不变的&#xff1a; X…

ONENET读取与控制麒麟座MINI开发板LED状态

硬件 麒麟座MINI开发板V1.4 嵌入式软件 OneNET_Demo_ESP8266_EDP_Led 工程修改内容 led.c文件修改 函数LED_Init&#xff0c;mini开发板LED所在GPIO为PB6、PB7、PB8、PB9 函数LED_GetValue&#xff0c;mini开发板LED状态与IO口状态相反 /** * brief LED指示灯初始化函数**/v…

activemq的使用场景

一、消息队列概述 消息队列中间件是分布式系统中重要的组件&#xff0c;主要解决应用耦合&#xff0c;异步消息&#xff0c;流量削锋等问题。实现高性能&#xff0c;高可用&#xff0c;可伸缩和最终一致性架构。是大型分布式系统不可缺少的中间件。 目前在生产环境&#xff0c…