文档章节

【Java并发编程实战】– 在同步代码中使用条件

pan_1308
 pan_1308
发布于 2017/09/07 17:21
字数 622
阅读 8
收藏 0
点赞 0
评论 0

一、概述

在并发编程中的一个经典问题是生产者与消费者问题:我们有一个数据缓冲区,一个或多个数据的生产者在缓冲区存储数据,而一个或多个数据的消费者,把数据从缓冲区取出。

由于缓冲区是一个共享的数据结构,我们必须采用同步机制,比如 synchronized 关键字来控制对它的访问。但是我们有更多的限制因素,如果缓冲区是满的,生产者不能存储数据,如果缓冲区是空的,消费者不能取出数据。

对于这些类型的情况,Java在Object对象中提供wait(),notify(),和notifyAll() 方法的实现。

 wait() 方法:

      1、只能在同步代码块中调用

      2、当一个线程调用 wait() 方法,jvm将这个线程置入休眠,并且释放控制这个同步代码快的对象,同时允许其他线程执行这个对象控制的其他同步代码块

      3、为了唤醒这个线程,必须在这个对象控制的某个同步代码快调用 notify() 方法或者 notifyAll() 方法

二、实现

import java.util.Date;
import java.util.concurrent.LinkedBlockingQueue;

/**
 * 中间缓存
 */
public class EventStorage {

	private int maxSize;
	private LinkedBlockingQueue<Date> storage;
	
	public EventStorage(int maxSize){
		this.maxSize = maxSize;
		storage = new LinkedBlockingQueue<Date>();
	}
	
	// 存放操作
	public synchronized void set(){
		// 在while循环中,你必须保持检查条件和调用wait()方法。你不能继续执行,直到这个条件为true。
		while(storage.size() == maxSize){ //循环判断 为 真,才进行 线程 挂起操作.
			try {
				wait(); // 挂起 该线程,等待 剩余空间出现
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		storage.offer(new Date());
		System.out.println("存操作- storage size:" + storage.size());
		notifyAll(); // 唤醒 所有 因为 wait() 操作而休眠的 线程.
	}
	
	// 取出操作
	public synchronized void get(){
		while(storage.size() == 0){ //循环判断 为 真,才进行 线程 挂起操作.
			try {
				wait(); // 挂起 该线程,等待 剩余空间出现
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		storage.poll();
		System.out.println("取出操作- storage size:" + storage.size());
		notifyAll(); // 唤醒 所有 因为 wait() 操作而休眠的 线程.
	}
}
import java.util.concurrent.TimeUnit;

/**
 *  生产者
 */
public class EventProducer implements Runnable{

	private EventStorage eventStorage;
	
	public EventProducer(EventStorage eventStorage){
		this.eventStorage = eventStorage;
	}
	
	@Override
	public void run() {
	   while(true){
		   eventStorage.set();
		   try {
			TimeUnit.SECONDS.sleep(1);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	   }
	}
}
/**
 * 消费者
 */
public class EventCustomer implements Runnable{
    
    private EventStorage eventStorage;
	
	public EventCustomer(EventStorage eventStorage){
		this.eventStorage = eventStorage;
	}

	public void run() {
		while(true){
			eventStorage.get();
			try {
				TimeUnit.SECONDS.sleep(2);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}
public class EventTest {

	public static void main(String[] args) {
		EventStorage eventStorage = new EventStorage(3);
		
		EventProducer producer = new EventProducer(eventStorage);
		EventCustomer customer = new EventCustomer(eventStorage);
		
		Thread threadProducer = new Thread(producer);
		Thread threadCostomer = new Thread(customer);
		
		threadProducer.start();
		threadCostomer.start();
	}
}

 

© 著作权归作者所有

共有 人打赏支持
pan_1308
粉丝 4
博文 93
码字总数 58819
作品 0
黄冈
Java 使用 happen-before 规则实现共享变量的同步操作

前言 熟悉 Java 并发编程的都知道,JMM(Java 内存模型) 中的 happen-before(简称 hb)规则,该规则定义了 Java 多线程操作的有序性和可见性,防止了编译器重排序对程序结果的影响。按照官方的...

stateIs0
01/20
0
0
Java多线程学习(二)synchronized关键字(2)

系列文章传送门: Java多线程学习(一)Java多线程入门 Java多线程学习(二)synchronized关键字(1) java多线程学习(二)synchronized关键字(2) Java多线程学习(三)volatile关键字 Ja...

一只蜗牛呀
04/16
0
0
计算机科学中抽象的好处与问题—伪共享实例分析

David John Wheeler有一句名言“计算机科学中的任何问题都可以通过加上一层间接层来解决”,一层不够就再加一层。后半句是我加的 (* ̄︶ ̄) ,虽然有点玩笑的意思,但是也的确能说明一些问题...

MageekChiu
01/10
0
0
【转】15个顶级Java多线程面试题及回答

Java 线程面试问题   在任何Java面试当中多线程和并发方面的问题都是必不可少的一部分。如果你想获得任何股票投资银行的前台资讯职位,那么你应该准备很多关于多线程的问题。在投资银行业务...

一只死笨死笨的猪
2014/09/30
0
0
关于Java里面多线程同步的一些知识

# 关于Java里面多线程同步的一些知识 对于任何Java开发者来说多线程和同步是一个非常重要的话题。比较好的掌握同步和线程安全相关的知识将使得我们则更加有优势,同时这些知识并不是非常容易...

欧阳海阳
07/13
0
0
【转】Java线程面试题Top50

目录(?)[-] 50道Java线程面试题 1 什么是线程 2 线程和进程有什么区别 3 如何在Java中实现线程 4 用Runnable还是Thread 6 Thread 类中的start 和 run 方法有什么区别 7 Java中Runnable和Cal...

gehui
2015/08/14
0
0
15个顶级Java多线程面试题及回答

Java 线程面试问题 在任何Java面试当中多线程和并发方面的问题都是必不可少的一部分。如果你想获得任何股票投资银行的前台资讯职位,那么你应该准备很多关于多线程的问题。在投资银行业务中多...

LCZ777
2014/05/27
0
0
Java 50道Java线程面试题

不管你是新程序员还是老手,你一定在面试中遇到过有关线程的问题。Java语言一个重要的特点就是内置了对并发的支持,让Java大受企业和程序员的欢迎。大多数待遇丰厚的Java开发职位都要求开发者...

swearyd457
2015/08/11
0
0
Android ThreadLocal+PriorityQueue构建多线程队列

一、消息队列 Android中使用了很多消息队列,如Intent,Handler,BroadcastReceiver等。使用消息队列的目的是防止线程阻塞并且将不能及时执行的任务缓存起来,从而提高系统的运行效率。 为了使...

IamOkay
2014/11/03
0
0
Java线程面试题 Top 50

不管你是新程序员还是老手,你一定在面试中遇到过有关线程的问题。Java语言一个重要的特点就是内置了对并发的支持,让Java大受企业和程序员的欢迎。大多数待遇丰厚的Java开发职位都要求开发者...

loda0128
2015/05/29
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

利用 acme.sh 获取网站证书并配置https访问

acme.sh 实现了 acme 协议, 可以从 letsencrypt 生成免费的证书.(https://github.com/Neilpang/acme.sh/wiki/%E8%AF%B4%E6%98%8E) 主要步骤: 安装 acme.sh 生成证书 copy 证书到 nginx/ap...

haoyuehong
9分钟前
0
0
微擎框架内如何根据media_id获取到微信图片的路径

微擎的框架内,图片选择后,获取的是那个字符串是media_id,相当于你这张图片在微信的图片服务器里面的id 要求是:获取https://mmbiz.qpic.cn/mmbiz_jpg/…… 微信图片的路径 而微信并没有根据m...

老bia同学
13分钟前
0
0
Spring boot中日期的json格式化

Model 在model层中,类的日期属性上面添加如下注解: @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd hh:mm:ss") 参考 Jackson Date格式化教程...

亚林瓜子
14分钟前
0
0
Eclipse:Failed to load the JNI shared library

1.问题背景: 由于我之前使用jdk1.9学习,当使用Luke的时候发现jdk版本过高,需要向下配置jdk,就向朋友拷了一个安装包。重新配置路径后,便开始报错。 2.问题描述: Failed to load the JNI...

tinder_boy
17分钟前
0
0
少儿学习编程课程是否真的适合七八岁的低龄儿童[图]

少儿学习编程课程是否真的适合七八岁的低龄儿童[图]: 天下熙熙皆为利来,天下攘攘皆为利往。 这几年来,乐高教育机构在国内如同雨后春笋般出现,当然关闭/转手的也很多。从教师角度来看,部...

原创小博客
22分钟前
0
0
ES12-词项查询

1.词项查询介绍 全文查询将在执行之前分析查询字符串,但词项级别查询将按照存储在倒排索引中的词项进行精确操作。这些查询通常用于数字,日期和枚举等结构化数据,而不是全文本字段。 或者,...

贾峰uk
30分钟前
0
0
http状态码与ajax的状态值

ajax状态值 1.1 200 & OK:状态请求成功

litCabbage
33分钟前
0
0
iOS动画效果合集、飞吧企鹅游戏、换肤方案、画板、文字效果等源码

iOS精选源码 动画知识运用及常见动画效果收集 3D卡片拖拽卡片叠加卡片 iFIERO - FLYING PENGUIN 飞吧企鹅SpriteKit游戏(源码) Swift封装的空数据提醒界面EmptyView 沙盒文件浏览与分享调试控...

sunnyaigd
37分钟前
0
0
AngularJS配置.run()块中设置路由事件的监听器以及过滤未经授权的请求

AngularJS中的run方法初始化全局数据,只对全局作用域起作用,如$rootScope.多个控制器之间可以共享数据,如下代码所示: <script type="text/javascript"> var m1 = angular....

孟飞阳
37分钟前
0
0
Java语言学习(十):输入/输出

Java中,I/O操作代表着输入、输出,Java所有的I/O机制都是基于数据流进行输入输出。java.io类包提供了很多的输入输出处理功能方法,大家可以参考下JDK文档中关于I/O的一些处理方法:JDK在线中...

海岸线的曙光
46分钟前
1
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部